【问题标题】:Why no "realloc" seems necessary when allocating new element to a char pointer?为什么在将新元素分配给 char 指针时似乎不需要“realloc”?
【发布时间】:2011-04-15 11:26:45
【问题描述】:

我正在尝试创建一个指向 char 指针的指针,我可以轻松地向该指针添加新元素(字符串)。当我想添加新项目时,我使用 malloc 创建前 2 个维度和 realloc。我编写了有和没有 realloc 的代码,我得到了相同的结果。这是预期/正常的行为吗?


使用 realloc

    char **p; // create pointer to char pointer
    p = malloc(sizeof(char*) * 2); // allocate 2 dimensions
    p[0] = "ab";
    p[1] = "cd";

    void* resizedP = (void*)realloc(p, sizeof(char*) * 4); // resize array
    p = (char**)resizedP;
    p[2] = "ef";
    p[3] = "gh";

    printf("%s \n", p[0]); // prints ab
    printf("%s \n", p[1]); // prints cd
    printf("%s \n", p[2]); // prints ef
    printf("%s \n", p[3]); // prints gh

    free(p);


没有重新分配

    char **p;
    p = malloc(sizeof(char*) * 2);

    p[0] = "ab";
    p[1] = "cd";
    p[2] = "ef";
    p[3] = "gh";

    printf("%s \n", p[0]); // prints ab
    printf("%s \n", p[1]); // prints cd
    printf("%s \n", p[2]); // prints ef
    printf("%s \n", p[3]); // prints gh

    free(p);

【问题讨论】:

  • 哦!我太想要一个无限的记忆库了!

标签: c arrays pointers


【解决方案1】:

绝对有必要调用realloc()来调整malloc()获得的内存块的大小。您通过访问超出已分配给程序的内存块的边界来调用未定义的行为

在您分配的内存块之后,您的第二个代码 sn-p 可能会运行一些重要数据。如果程序甚至因为越界错误而尝试访问另一个进程中的内存块,操作系统会大声抱怨(导致分段错误)。

无法保证您的第二个代码 sn-p(没有 realloc())将来不会崩溃或以其他方式失败。这次只是碰巧奏效了。

【讨论】:

  • 非常感谢您的回答!
  • 从技术上讲,它不能也不会在任何会 SIGSEGV 进程的系统上运行另一个进程的内存。更像是它可以引用未标记为写入访问的段或没有映射到它的框架的页面。
  • @Novikov:是的,操作系统应该在另一个程序运行之前停止对内存的访问。我已经编辑了我的帖子以使其更清晰。
【解决方案2】:

在您的情况下,这可能是巧合。例如,您的 C 库的 malloc() 可能决定将您的分配大小填充某个数字,恰好是 >= 2*sizeof(void*)

但是,理论上,没有什么可以阻止后续的malloc 返回恰好位于p[2] 的字节。也没有什么可以阻止malloc 返回一个值,在您请求的大小之后,操作系统没有将任何页面映射到地址空间。因此,您不应依赖此行为。不要在没有分配正确数量的情况下写信给p[2],因为这可能导致以下任何一种情况:

  • 您覆盖了某个其他函数已写入的值。
  • 其他一些功能可能会在以后覆盖您。
  • 尝试访问它可能会崩溃。

【讨论】:

    【解决方案3】:

    尝试通过 valgrind 或使用 -fstack-protector 编译器开关运行您的第二个选项。您可能会获得有关 In silico 的答案为何正确的更多信息。

    【讨论】:

    • 谢谢,我阅读了解释 valgrind 的作用和工作原理的文档。我肯定会尝试它,但在另一个安装了 Linux 的机器上。
    【解决方案4】:

    假设您的p 是一辆可容纳 20 人的巴士。

    然后你尝试在里面放 30 个人(不扩大它)。有时它会起作用,如果他们不胖 ...

    对于C,这是未定义的行为。任何事情都有可能发生。刚才你运气不好,它“奏效了”。

    简而言之:不要那样做!

    【讨论】:

      【解决方案5】:

      哇,不要做那个人!它起作用是有原因的,但它只是麻烦。

      首先,p 不是一个数组,它是一个指针,您可以通过检查sizeof(p) 看到这一点,它总是返回 4 或 8,具体取决于您运行的是 32 位还是 64 位系统。

      指针指的是内存中的一个位置,因此如果您尝试打印一个指针,您将获得一个内存地址,例如 32 位机器上的 0x0B32D2F1,当您调用其中一个 *alloc 函数时,处理器找到您请求大小的空闲内存块,并将其分配给您的程序。

      您所做的是访问和编辑尚未分配给您的内存,虽然很容易,但没有什么能阻止您这样做,但这很糟糕,因为该内存可能会分配给不同的程序,然后用户当你让他的其他程序崩溃时会恨你。简而言之,始终分配您将使用的内存!永远!

      哦,是的,那么处理器可能会将您正在使用的未分配内存分配给另一个程序,这会弄乱您的程序。

      【讨论】:

      • 感谢您指出我在数组和指针之间的混淆。我编辑了问题的标题。
      猜你喜欢
      • 2021-09-02
      • 2020-11-13
      • 2011-10-11
      • 2020-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-04
      • 2014-04-02
      相关资源
      最近更新 更多