2

I have problems with array pointers in c/objective c. When I execute my code I get a BAD ACCESS error message. I nailed down the statement that crashes the app:

unsigned char *image[640][480][4];

If I change the statement to:

unsigned char *image[640][10][4];

the program doesn't crash.

This statement crashes the app as well:

unsigned char *bla[1000][180];

Any idea why the size of the array causes the crash to occur? This is just a declaration of an array pointer.

I'm running Xcode 4.2.1 with IOS 5 target.

7
  • 1
    Next time, please work on code formatting before you post, thank you. Commented Jan 14, 2012 at 21:00
  • What happens if you try using malloc instead, out of curiosity? Commented Jan 14, 2012 at 21:01
  • post the code that causes the crash. Commented Jan 14, 2012 at 21:03
  • 1
    You're probably trying to allocate the array on the stack. It's too big for that. Use the heap. Commented Jan 14, 2012 at 21:04
  • 1
    @BoE It crashes at declaration because it cannot find enough memory for declaring. Looks like you meant pointer to such an array, in that case you should use char (*image)[640][480][4] - this is a pointer to a three dimensional array. You declared a three dimensional array of pointers. Commented Jan 14, 2012 at 21:18

3 Answers 3

6

iOS's main thread stack can hold up to 1MB, but your array is 640 * 480 * 4 * sizeof(unsigned char*) bytes, which is rougly 4.68MB. Therefore, this allocation cannot succeed on the main thread. You should use a dynamic allocation instead, which will use memory from the heap.

If what you really meant is that image is a pointer to a three-dimensional array, I encourage you to use a typedef to make it easier to read:

typedef unsigned char image_array[640][480][4];
image_array* pointer = ...; // pointer to 640 * 480 * 4 unsigned chars
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for giving us the exact stack limit and a link to its publication - ty!
4
char *image[640][480][4];

That is 640 * 480 * 4 * sizeof(char*) bytes (approximately 4.68mb) of memory in the stack. I am guessing your app doesn't have that much stack available. Take it to heap - generally its not a good idea to have such huge stuff on the stack (as local variables).

Do this instead:

char *image;

image = malloc(640 * 480 * 4 * sizeof(char*));

if(!image){
  printf("oops - even malloc failed\n");
  exit(1);
}

Note that you cannot access image as a three dimensional array anymore. Statements such as image[i][j][k] should be replaced with image[i * 480 * 4 + j * 4 + k]

You can use a macro here:

#define GET_IMAGE_POINTER_AT(image, i, j, k)  (image[(i) * 480 * 4 + (j) * 4 + k])

5 Comments

It's not 640*480*4 bytes. It's 640*480*4 pointers, so it's much more. (The error may also be using char *image[640][480][4] as a char (*image)[640][480][4].
Thanks Amarghosh. What I'm trying to do is to create an array pointer with with three dimensions [640][480][4] that "points" to a byte array (of size 640*480*4 bytes). I don't want to allocate any new memory. I want to access the data like this: unsigned char red = image[200][300][0]; Any idea how to accomplish this?
Assume you have an array like char ar[640][480][4], you can do something like char (*image)[480][4]=ar. It's just assign array to a pointer. Also, you can do more complex stuff, like char (*image)[480][4]=malloc(640*480*4);
@Bo E you can access it the same way, it dosent matter if its allocated on the stack or heap
@asaelr Looks like you are correct about declaration - please post it as the answer
3

If what you're wanting to do is to declare image as a pointer to an array, and not an array of pointers, then you should declare it as so:

unsigned char (*image)[480][4];

You don't specify the first dimension of the array, because that's where this pointer is pointing - to the first element in the array. The * essentially replaces the [640].

Then, for example if you had an array unsigned char test[640][480][4] (assuming this didn't crash), your code would simply be:

unsigned char test[640][480][4];
unsigned char (*image)[480][4] = test;

Your code declares a multi-dimensional array of char*s, whereas this code declares a pointer to a multi-dimensional array of chars.

The reason why changing 480 to 10 may stop the code from crashing is because you're most likely trying to use up more space than what's available on the stack, by creating an actual array of such a large size as opposed to a pointer to one.

4 Comments

if image should point to only one 3d array (not array of them), you should remove the [640]
Thanks! I get it. Really appreciate explanation.
@BoE: I edited my code to fix an error pointed out by asaelr. Without removing the [640] you'd have to refer to an element as *image[0][0][0] as opposed to image[0][0][0].
Thanks AusCBloke and asaeir. Really appreciate your explanations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.