【问题标题】:Why NULL ing pointer before using it in realloc function?为什么在 realloc 函数中使用 NULL 指针?
【发布时间】:2017-10-21 10:51:03
【问题描述】:

如果我使用malloc 执行以下操作

HashTableEntry *util = malloc(sizeof(HashTableEntry) * T->capacity);

一切正常。但是,如果我使用realloc 执行以下操作

HashTableEntry *util = realloc(util, sizeof(HashTableEntry) * T->capacity);

realloc 返回NULL。我还收到 gcc 的警告,说我在使用之前没有初始化 util。

但是,下面的效果很好,比如malloc

HashTableEntry *util = NULL;
util = realloc(util, sizeof(HashTableEntry) * T->capacity);

我的问题是为什么?

我相信正在发生的事情是,在所有情况下,我都在创建一个指针并将我正在分配的堆内存块的起始地址分配给它。我是不是哪里错了?

【问题讨论】:

  • 典型的使用模式是malloc初始块然后realloc如果/当需要。将NULL 传递给realloc 只是调用malloc 的一种奇怪方式。
  • 不,这并不奇怪。函数的参数应该总是被初始化,因为函数可能使用参数的值。如果不初始化参数,编译器不知道该怎么做。
  • 当您将 未初始化 垃圾指针传递给 realloc 时,您期望它如何工作?您是如何期望 realloc 知道您希望它充当 malloc 的?
  • @user3386109:典型的使用模式是将指针设置为空,然后仅使用realloc,利用realloc(NULL, 等价于malloc这一事实。这会产生更优雅和更紧凑的代码,而无需不必要的分支和/或拆分。然而,很多人不知道他们可以在这样的代码中统一使用realloc,因此他们坚持将第一次分配分成“特殊情况”并使用malloc。这会导致更丑陋的代码。

标签: c pointers null allocation realloc


【解决方案1】:

从函数调用中可以看出

HashTableEntry *util = realloc(util, sizeof(HashTableEntry) * T->capacity);

函数realloc 使用参数util。如果它具有不确定的值,则该函数具有未定义的行为。

在使用任何函数之前,你应该阅读它的描述和每个参数的用途。

来自 C 标准(7.22.3.5 realloc 函数)

2 realloc 函数释放指向的旧对象 ptr 并返回一个指向具有大小的新对象的指针 由大小指定....

和

3 如果 ptr 是空指针,realloc 函数的行为类似于 指定大小的 malloc 函数。

【讨论】:

  • @RestlessC0bra 扩展内存函数必须知道要扩展的内存地址。我已经写过,如果第一个参数的值不确定,那么该函数具有未定义的行为。
【解决方案2】:

通常,函数会查看其参数的值并使用这些值来执行某些操作,因此传递特定值而不是随机或未指定的值很重要。当您编写HashTableEntry *util = realloc(util, sizeof(HashTableEntry) * T->capacity); 时,您还没有告诉编译器在调用util 函数时将什么值放入realloc 函数中,因此您可能会得到未定义的行为,这很糟糕。

【讨论】:

  • 嗯?不,仔细看看你是如何调用malloc的。您没有将 util 作为参数传递给 malloc,因此没有问题。当您调用realloc 时,您将util 作为参数传递,因此必须先对其进行初始化。
  • 参数是你在函数名后面的括号内写的东西。它们是函数的输入,因此您必须在调用函数之前确定它们应该具有的值。
【解决方案3】:
  1. 如果第一个参数是空指针,realloc() 的行为类似于指定大小的 malloc()。

  2. 如果第一个 arg 是未初始化的指针(坏指针),realloc() 将无法正常工作,因此返回 NULL。

  3. 如果第一个参数是有效地址,realloc() 释放旧对象并返回指向新对象的指针,或者扩展旧对象的内存(由操作系统决定)。

【讨论】:

    【解决方案4】:

    在第二种情况下,util 在传递到 realloc() 时未初始化。 所以realloc() 的行为是不确定的。

    HashTableEntry *util = realloc(util, sizeof(HashTableEntry) * T->capacity);
                                 //^^^^ This value is undefined.
    

    在第三种情况下,您将其初始化为 NULL,在这种情况下,realloc() 的行为类似于 malloc()。

    【讨论】:

      【解决方案5】:

      注意事项:

      当调用realloc() 时不要直接赋值给目标指针。而是分配给临时指针,然后在分配给目标指针之前检查 (!=NULL)。

      然后,如果/当realloc() 失败时,原始指针不会丢失。丢失这样的指针会导致内存泄漏。

      注意:realloc() 的第一个参数是一个“源”指针。它必须指向有意义的东西,例如NULL 或堆中的已知位置。

      【讨论】:

        猜你喜欢
        • 2019-10-25
        • 2013-12-27
        • 2021-08-04
        • 1970-01-01
        • 2010-09-17
        • 1970-01-01
        • 1970-01-01
        • 2015-02-04
        • 2016-08-23
        相关资源
        最近更新 更多