【问题标题】:c - Pointer of array initialized in a function contains wrong values after returningc - 在函数中初始化的数组指针在返回后包含错误的值
【发布时间】:2013-03-28 10:06:08
【问题描述】:

我遇到了一个问题,而且我肯定做错了什么。 我需要调用一个函数,该函数返回一个指向 int 数组的指针,但是当它返回后,数组中的值是错误的,并且某些值丢失了。

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;
}

如果 digit = 1,这里是打印的内容

1, 1, 2, 1, 2, 2

但返回后

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

这是打印的内容

1, -1405451528, -1405449120, 366001

你知道出了什么问题吗?

谢谢大家

PS:我使用的是 Xcode 4.6,我的项目使用的是 ARC,但我很确定这不是我的问题的原因。

【问题讨论】:

  • 您正在返回一个指向临时数组的指针。
  • 在 SO 上每天会被询问大约 20 次相同的“常见问题解答”。希望有办法阻止它。

标签: c arrays pointers memory-management int


【解决方案1】:

您不能返回指向在函数中创建的数组的指针。该数组在函数返回后不再存在,因此您的指针指向内存中某个随机的无效位置。

为指针分配内存(例如使用malloc()),然后返回一个指针。这也意味着您需要在完成后释放一个指针(使用free())。

伪代码类似于:

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);

【讨论】:

  • 我按照你的建议做了,但还是不行:int *pattern = malloc(sizeof(int) * 6);模式 = (int [6]){1,1,1,1,1,1};但是当我返回值仍然错误并且当我尝试释放它时收到此消息 malloc: *** 对象 0xbfffda9c 的错误:未分配指针被释放 *** 在 malloc_error_break 中设置断点以进行调试
  • @Dave - 您不能以这种方式将数组分配给指针。您可以使用示例:pattern[0] = 0; pattern[1] = 1; ....
  • @kamituel OMG,这很痛苦。我的开关中有 10 个案例,我的数组中有 6 个值,所以我需要做 pattern[n] = ...; 60 次?我不能像这样在一行上初始化数组吗:{1,1,2,1,2,2}?
  • @Dave - 您可以在函数中创建一个本地数组,然后在for 循环中将内容复制到pattern。这样pattern会在函数返回时生效。
【解决方案2】:

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

是函数中定义的局部数组。因此,当函数完成执行时,可以删除数组的数据。所以这就是为什么你在你的printf中得到垃圾值

1) 改用malloc 分配数组

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;
}

pattern 变得无用时,您的代码中的某些位置然后使用free(pattern); 释放它

2) 或者在数组的定义中使用static

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;
}

【讨论】:

  • static 不起作用我收到预期的表达式错误。你知道为什么吗?
  • @Dave 你是对的,这是我的代码中的一个错误。答案已更新
【解决方案3】:

问题是因为您正在返回一个局部变量。局部变量是一个临时变量,在其范围消失后不再可用。您可以尝试以下方法:

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;
}

那么你可以像这样使用它:

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

【讨论】:

  • 绝对错误。修复你的代码,有被否决的风险
  • pattern = malloc(...); pattern = (int [6])... :您只是从 malloc 中泄漏了内存,而没有解决问题。如果您将模式分配替换为分配内存中的副本,那将是一个更好(但仍然很差)的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多