1

I'm trying to write a function in C, which returns the pointer to an array. Each element of this array is a pointer to the initialized structure, and in each structure there's also a pointer to an array.

struct queueRecord;
typedef struct queueRecord* queue;

queue createQueue(int maxSize){
    queue newQueue = malloc(sizeof(struct queueRecord));
    newQueue->array = malloc(sizeof(int)*maxSize);
    newQueue->capacity=maxSize;
    newQueue->front=0;
    newQueue->rear=0;
    return newQueue;
}

This just works fine as well as in the following function:

queue* initQArr(int maxSize){
    queue arr[10];
    for (int i=0; i<10; i++) {
        arr[i]=createQueue(maxSize);
    }
    return arr;
}

when I pass the parameter 10 in it and set a breakpoint at return, everything seems good (excuse me I can't post images, the debug information is like following):

arr(queue[10])
 [0]=(queue)0x100105480
   capacity=(int)10
   size=(int)0
   front=(int)0
   rear=(int)0
   array=(int*)0x1001054a0
 [1]=(queue)0x1001054d0
 ...
 ...
 [9]=(queue)0x100105760

However!When I invoke this function and return to a new array, I got an array with only 5 elements:

queue *digitsQArr = initQArr(length);
int digit = 0;

(debug information as following):

digitQArr = (queue*)0x7fff5fbff6d0
    *digitsArr=(queue)0x100105480
        capacity=(int)10
        size=(int)0
        front=(int)0
        rear=(int)0
        array=(int*)0x1001054a0
    [1]=(queue)0x1001054d0
    ...
    ...
    [4]=(queue)0x1001055d0
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
Karl Bao
  • 401
  • 2
  • 4
  • 11
  • 2
    You are returning an array that goes out of scope when the function initQArr finishes execution. You must dynamically allocate memory to "arr" and return that. – itachi Apr 28 '15 at 18:36
  • In case you're wondering why there appeared to be five valid elements, [**this question**](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) is directly related. And fyi, [**the selected answer**](http://stackoverflow.com/a/6445794/1322972) is *stellar*. – WhozCraig Apr 28 '15 at 18:43
  • Or declare it as `static`. E.g. `static queue arr[10];` – David C. Rankin Apr 28 '15 at 18:43
  • @itachi I try to declare _arr_ as `queue* arr=malloc(sizeof(struct queueRecord)*10)`, then _arr_ also has only 5 elements when in the function. There must be something wrong when I allocate the memory... – Karl Bao Apr 28 '15 at 18:48
  • @itachi hey you are right! It works after dynamically allocate memory to `arr`. What is confusing is that only 5 of them are displayed in debug mode in XCODE... Anyway, the program works fine now. Thanks! – Karl Bao Apr 28 '15 at 20:03

1 Answers1

2

In initQArr, you return the address of a local variable, arr:

queue* initQArr(int maxSize){
    queue arr[10];
    for (int i=0; i<10; i++) {
        arr[i]=createQueue(maxSize);
    }
    return arr;
}

The returned pointer will point to the local array arr, which is no longer valid once the function returns. You could follow the example of createQueue and allocate memory on the heap:

queue* initQArr(int maxSize){
    queue *arr = malloc(10 * sizeof(*arr));
    for (int i=0; i<10; i++) {
        arr[i]=createQueue(maxSize);
    }

    return arr;
}

After returning, the pointer arr is still valid, because it points to memory on the heap. You should free such memory after using it, like the queue pointers allocated in createQueue.

M Oehm
  • 28,726
  • 3
  • 31
  • 42
  • But when I use `queue *arr = malloc(10 * sizeof(*arr));` ,I got an `arr` with only 5 valid elements even in the function `initQArr` – Karl Bao Apr 28 '15 at 19:01
  • How do you check this? Do you print the array contents and get weird pointers? What do you mean with "valid" element? – M Oehm Apr 28 '15 at 19:39
  • **It works** after I dynamically allocate the memory! However, only 5 elements are displayed in the debug window when I debug in XCODE, so weird... – Karl Bao Apr 28 '15 at 20:00
  • I'm not familiar with Xcode or its debugger, but because C arrays don't know about their size, the debugger can't either. In gdb (which appears to be one of the debuggers supported by Xcode), you'd have to print `p *arr@10`, where the number after the `@` is how many entries you want to print. – M Oehm Apr 28 '15 at 20:03