4

Returning an array (Warning: Function returns address of local variable) ?

interface

int* decimalConversion(int iX);

implementation

int* decimalConversion(int iX){
    int iMult[10] = {0,0,0,0,0,0,0};

    ...

    return iMult;  // <-- Warning: Function returns address of local variable
}
Kristen Martinson
  • 1,829
  • 3
  • 22
  • 33

2 Answers2

12

You should allocate space for the array, you're returning the address of an array that was created on the stack (hence local variable warning) if you're using C in that function use malloc(my_arr_size) if not use obj-c's alloc.

Example:

int *my_arr = calloc(10, sizeof(int)); //make sure we get zeroed memory
//fill array
return my_arr; //should no longer give a warning

When done with it just use free(my_arr) same as release. Reason I did this in C is because I can see that you're returning an int* type and using C style declarations so if you're doing it in Obj-c let me know and I can change my answer's example.

The reason you are getting this error is because local arrays get put on the stack, when you return that array you return an address in a stack frame. The problem is that when that method finishes execution that stack frame is no longer valid and therefore you cannot expect any data that was on that frame to be valid (although there are cases when this does work but it is considered bad practice). By allocating that array on the heap you can return a heap address where your data is assured to exist until you call free() on the pointer to that data.

Jesus Ramos
  • 22,940
  • 10
  • 58
  • 88
  • Ok then follow my answer and you should be just fine :) – Jesus Ramos Jul 24 '11 at 00:57
  • Not sure why that clears the Warning? Using calloc to declare an array vs just declaring an array with "[ ]" both yield a pointer. The answer returned by the function is the same in both cases. I just get a warning with the other ???? With respect to calloc or malloc, depending on method calls, I have to use "retain" or the array gets lost. So I don't understand the difference? – Kristen Martinson Jul 24 '11 at 01:11
  • When you define with [] you define it on the stack because the size is known, when you define with malloc or alloc you define it in the heap which unlike a stack frame is always valid until the heap block you asked for gets freed. – Jesus Ramos Jul 24 '11 at 01:46
  • um... if memory arrays are put on the stack, you are then using push and pop. You can't index into it without popping everything off to get to that item, push and pop it on the stack somewhere else to keep it?, and then you push it back on to keep the array. Indexing memory using an array is dynamic memory done on the heap. – jdl Jul 24 '11 at 02:41
  • @jdl, ummmm no. You can use pointer arithmetic which is what the compiler does. His issue is that the stack frame is INVALID once the method finishes (not guaranteed data correctness) so the data could possibly be invalid since invalid stack frames do not get preserved – Jesus Ramos Jul 24 '11 at 02:42
  • Please try to keep comments coherent, constructive and on topic. – Tim Post Jul 24 '11 at 07:19
0

If you are doing this for an app written in Objective-C, I would suggest using NSArray. NSArray is an Objective-C class for immutable arrays, and doesn't require that you manually allocate memory. The only turnoff is that you have to encapsulate your integers in NSNumber objects. An example would be:

NSArray * getNums (int num) {
    NSArray * result = [NSArray arrayWithObjects:[NSNumber numberWithInt:num-1], [NSNumber numberWithInt:num], [NSNumber numberWithInt:num+1], nil];
    return result;
}
...
NSArray * myList = getNums(10);
NSLog(@"First: %d", [[myList objectAtIndex:0] intValue]);
NSLog(@"Second: %d", [[myList objectAtIndex:1] intValue]);
NSLog(@"Third: %d", [[myList objectAtIndex:2] intValue]);

You can alternatively do this:

NSArray * getNums (int num) {
    NSMutableArray * array = [NSMutableArray array];
    [array addObject:[NSNumber numberWithInt:num-1]];
    [array addObject:[NSNumber numberWithInt:num]];
    [array addObject:[NSNumber numberWithInt:num+1]];
    return array;
}
...
NSArray * myList = getNums(10);
for (int i = 0; i < [myList count]; i++) {
    NSLog(@"myList[%d] = %d", i, [myList objectAtIndex:i]);
}

The only difference is that NSMutableArray allows you to add/remove elements after the fact.

Alex Nichol
  • 7,512
  • 4
  • 32
  • 30