0

I'm facing an issue and I'm certainly doing something wrong. I need to call a function that returns a pointer to an array of int but when after it returns, the values inside the array are wrong and some values are missing.

int* patternForFirstDigit(int digit) {
    int *pattern;
    pattern = (int [6]){1,1,1,1,1,1};

    switch (digit) {
        case 0:
            pattern = (int [6]){1,1,1,1,1,1};
            break;

        case 1:
            pattern = (int [6]){1,1,2,1,2,2};
            break;

        default:
            pattern = (int [6]){0,0,0,0,0,0};
            break;
    }

    for (int i = 0; i < 6; i++) {
         printf("%i\n", pattern[i]);
    }

    return pattern;
}

In case of digit = 1, here's what's printed

1, 1, 2, 1, 2, 2

But after returning

int *pattern = patternForFirstDigit(0);
for (int i = 0; i < 6; i++) {
     printf("%i\n", pattern[i]);
}

here's what's printed

1, -1405451528, -1405449120, 366001

Do you have an idea of what's wrong ?

Thanks guys

PS : I'm using Xcode 4.6 and my project is using ARC but I'm pretty sure it's not the reason of my problem.

2
  • You're returning a pointer to a temporary array. Commented Mar 28, 2013 at 10:07
  • 1
    This same "FAQ" gets asked about 20 times a day on SO. Wish there was a way to prevent it. Commented Mar 28, 2013 at 10:07

3 Answers 3

5

You can not return a pointer to an array created in a function. This array is no longer existing after a function returns, so your pointer points to some random, invalid place in a memory.

Allocate memory for a pointer (using malloc() for instance) and then return a pointer. This would also mean you'd need to free a pointer after you're done with it (with free()).

Pseudocode for this would be something like:

int* patternForFirstDigit(int digit) {
  int *pattern = (int*) malloc(sizeof(int)*N);
  pattern[0] = 0;
  pattern[1] = 1;
  ...

  // Alternatively just create a local array and use a for-loop
  // to copy the contents to the pattern array.

  return pattern;
}

int *p = patternForFirstDigit(M);
// use p
free(p);
Sign up to request clarification or add additional context in comments.

4 Comments

I did what you suggest but it still doesn't work : int *pattern = malloc(sizeof(int) * 6); pattern = (int [6]){1,1,1,1,1,1}; but when i return values are still wrong and i get this message when i try to free it malloc: *** error for object 0xbfffda9c: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug
@Dave - you cannot assign a array to a pointer this way. You could use on example: pattern[0] = 0; pattern[1] = 1; ....
@kamituel OMG that's a pain. I've 10 case in my switch and I have 6 values in my array so I need to do pattern[n] = ...; 60 times ? Can't I initialize the array on one line like this format : {1,1,2,1,2,2} ?
@Dave - you can create a local array in a function and then, in a for loop, copy the contents to the pattern. This way pattern will be valid when function returns.
1

the

(int [6]){1,1,2,1,2,2};

is a local array defined in the function . so the data of the array could be erased when the function finish the execution. so that's why you get garbage values in your printf

1) Use malloc to allocate array instead

int* patternForFirstDigit(int digit) {
    int *pattern = malloc(6*sizeof(int));

    memcpy(pattern, (int [6]){1,1,1,1,1,1}, 6*sizeof(int));

    switch (digit) {
        case 0:
            memcpy(pattern, (int [6]){1,1,1,1,1,1}, 6*sizeof(int));
            break;

        case 1:
            memcpy(pattern, (int [6]){1,1,2,1,2,2};, 6*sizeof(int));
            break;

        default:
            memcpy(pattern, (int [6]){0,0,0,0,0,0}, 6*sizeof(int));
            break;
    }

    for (int i = 0; i < 6; i++) {
         printf("%i\n", pattern[i]);
    }

    return pattern;
}

and some where in your code when the pattern became useless then free it with free(pattern);

2) Or use static in the definition of the array:

int* patternForFirstDigit(int digit) {
    int *pattern; int i;
    static int A[6]={1,1,1,1,1,1};
    static int B[6]={1,1,2,1,2,2};
    static int C[6]={0,0,0,0,0,0};
    pattern = A;

    switch (digit) {
        case 0:
            pattern = A;
            break;

        case 1:
            pattern = B;
            break;

        default:
            pattern = C;
            break;
    }

    for (i = 0; i < 6; i++) {
         printf("%i\n", pattern[i]);
    }

    return pattern;
}

2 Comments

static doesn't work I get an Expected expression error. Do you have an idea why ?
@Dave you are right it's a mistake in my code. answer updated
0

The problem is because you are returning a local variable. A local variable is a temporary one that is no longer available after its scope is gone. You may try the following:

int* patternForFirstDigit(int digit, int* pattern) {

    int* pattern1 = (int [6]){1,1,1,1,1,1};
int i;
    switch (digit) {
        case 0:
            pattern1 = (int [6]){1,1,1,1,1,1};
            break;

        case 1:
            pattern1 = (int [6]){1,1,2,1,2,2};
            break;

        default:
            pattern1 = (int [6]){0,0,0,0,0,0};
            break;
    }
memcpy(pattern,pattern1,6*sizeof(int));
    for ( i = 0; i < 6; i++) {
         printf("%i\n", pattern[i]);
    }
    return pattern;
}

Then you may use it like:

pattern = malloc(6*sizeof(int));
pattern=patternForFirstDigit(1, pattern);
int i;
for ( i = 0; i < 6; i++) {
     printf("%i\n", pattern[i]);
}
free(pattern);

2 Comments

DEFINETLY WRONG. fix your code, there is a risk to get downvoted
pattern = malloc(...); pattern = (int [6])... : You just leaked the memory from malloc, without fixing the problem. If you replaced the pattern assignments with copies into the allocated memory, that would be a better (but still poor) solution.

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.