【问题标题】:Function for allocating arrays in other function in C用于在 C 中的其他函数中分配数组的函数
【发布时间】:2015-08-06 18:56:20
【问题描述】:

我在使用一个函数在另一个函数中分配数组时遇到问题。这是导致问题的部分:

void
array_allocator(int method, int** a, int** b){
  if (method == 0)
  {
    (*a) = (int[5]) {0, 1, 2, 3, 4};
    (*b) = (int[5]) {5, 6, 7, 8, 9};

    printf ("in array_allocator\n");
    printf ("a = (%d, %d, %d, %d, %d)\n",(*a)[0],(*a)[1],(*a)[2],(*a)[3],(*a)[4]);
    printf ("b = (%d, %d, %d, %d, %d)\n",(*b)[0],(*b)[1],(*b)[2],(*b)[3],(*b)[4]);
  }
  else printf("unknown method\n");
}

void
some_function (int method){
  int *a, *b;

  array_allocator(method, &a, &b);

  printf ("in some_function\n");
  printf ("a = (%d, %d, %d, %d, %d)\n",a[0],a[1],a[2],a[3],a[4]);
  printf ("b = (%d, %d, %d, %d, %d)\n",b[0],b[1],b[2],b[3],b[4]);
}

int main()
{
  int method = 0;
  some_function(method);
  return 0;
}

使用 gcc 编译并执行后,我得到了输出:

in array_allocator
a = (0, 1, 2, 3, 4)
b = (5, 6, 7, 8, 9)
in some_function
a = (10, 0, 4196346, 0, 1448083200)
b = (-730692608, 32637, 16, 0, 4196346)

不知何故,数组分配后的值变得随机,如果我在some_function()打印数组值之前添加一些printf()函数,甚至会改变。

【问题讨论】:

  • 你实际上并没有分配。你可能想要malloc。更高级的可能性是划分现有块(甚至可能是静态/全局内存)并将其称为“已分配”,但您不能像现在这样使用堆栈内存。我推荐malloc 或操作系统调用来获取内存。

标签: c arrays pointers compound-literals


【解决方案1】:

在您的 array_allocator() 函数中,您使用的是复合文字。

关于复合文字的使用,引用C11 标准,第 §6.5.2.5 章,(强调我的

[...] 如果复合文字出现在函数体之外,则该对象具有静态存储持续时间; 否则,它具有与封闭块关联的自动存储持续时间。

所以,一旦你的函数返回,复合文字就不再存在了。因此,在some_function() 中解引用a 又是UB。

解决方案:您可能希望通过malloc() 或family 使用动态内存分配。动态分配内存的生命周期保持有效,除非使用 free() 调用解除分配(或者,挑剔,直到程序终止,以较早者为准),因此即使在函数返回后,您也可以使用它。

【讨论】:

    【解决方案2】:

    这不起作用,因为您分配的值仅存在于本地:

    (*a) = (int[5]) {0, 1, 2, 3, 4};
    (*b) = (int[5]) {5, 6, 7, 8, 9};
    

    你应该这样做:

    *a = malloc(sizeof(int)*5);
    *b = malloc(sizeof(int)*5);
    (*a)[0] = 0;
    (*a)[1] = 2;
    (*a)[2] = 2;
    (*a)[3] = 3;
    (*a)[4] = 4;
    (*b)[0] = 5;
    (*b)[1] = 6;
    (*b)[2] = 7;
    (*b)[3] = 8;
    (*b)[4] = 9;
    

    另外,不要忘记free(a)free(b)some_function() 的末尾

    【讨论】:

    • 感谢您的回复,我认为执行 (*a) = (int[5]){0,1,2,3,4} 与分配内存并稍后定义输入相同,但显然不是。谢谢。
    【解决方案3】:

    这里的问题是范围:您的 array_allocator 仅在其自身执行期间分配数组。 “已分配”数组在 array_allocator 范围内是本地的,因此当它返回时,它们可能不再被使用。

    要分配超出调用者范围的内存,请使用malloc。但别忘了也free它!

    【讨论】:

      【解决方案4】:

      abarray_allocator 的局部变量。局部变量在堆栈上,只有在函数内部时才可用。返回后,堆栈将被覆盖,包括您的 ab。您看到的是那些新的“随机”堆栈值。

      您需要使用malloc。但是,在完成ab 之后,你必须确保你是freeing 内存。

      阅读 C 中的指针和数组;网上有很多很好的资料,只需一个 duckduckgo 搜索即可。

      【讨论】:

      • 问题不在于它们是本地的;这是他们有自动存储期限。如果对象是static,尽管变量是本地的,代码仍然可以工作。此外,没有必要提及“堆栈”——就 C 而言,没有“堆栈”。这是公认的常见实现细节,但它无关紧要,因为语言本身的抽象语义足以描述为什么有问题的代码不正确。
      • @TheParamagneticCroissant 是的,问题是它们是本地的。但你是对的,它们也不应该是static。我试图对似乎是初学者的问题给出一个务实的(双关语)解释。这就是为什么我也提到了堆栈,但没有给出理论解释,让事情变得不那么清楚。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 2018-06-09
      相关资源
      最近更新 更多