【问题标题】:realloc fails after multiple calls only when not debuggingrealloc 仅在不调试时在多次调用后失败
【发布时间】:2013-08-20 15:13:11
【问题描述】:

下面的代码偶尔会在 buffer = (char*) realloc(buffer, allocated * sizeof(char)); 调用(在下面标记)上失败,我用它来为 char* 动态分配空间,最初分配 1 个字符,每次我已经拥有的内存时将分配的数量加倍不足以存储字符串。

我的项目的许多其他部分都有非常相似的代码,具有相同的内存分配策略和调用(仅更改我传递给reallocvoid* 的类型)。

我是用VS2010调试的问题,当我在调试模式下启动程序时,功能总是成功完成。

但是,当从命令行调用程序时,对 realloc 的调用很可能会在一段时间后失败并出现“访问冲突读取位置”错误 - 尽管它不会一直发生, 并且仅在多次调用下面的函数之后发生,并且已经发生了许多重新分配。

更奇怪的是,我在 realloc 调用之前和之后打印了一些内容,以断言指针位置是否已更改,当我这样做并运行程序时,对 realloc 的调用随机停止失败。

我做错了什么?

TOKEN
next_token_file(FILE* file, 
                STATE_MACHINE* sm, 
                STATE_MACHINE* wsssm)
{
    char* buffer = (char*) malloc(sizeof(char));
    size_t allocated = 1;
    size_t i = 0;
    while(1)
    {
    /*
    ... code that increments i by one and messes with sm a bit. Does nothing to the buffer.
    */
        // XXX: This fails when using realloc. Why?
        if(i + 1 >= allocated)
        {
            allocated = allocated << 1;
            buffer = (char*) realloc(buffer, allocated * sizeof(char));
        }
        buffer[i] = sm->current_state->state;
    /*
    ... more code that doesn't concern the buffer
    */
    }
    // Null-terminate string.
    buffer[++i] = 0;
    TOKEN t = {ret, buffer};
    return t;
}

【问题讨论】:

  • 这个size_t allocated = 1;不应该是size_t allocated = 16;吗?
  • 这是我的猜测,或者他真的想在第一轮从 16 个字符减少到 2 个字符(这会……很奇怪)。

标签: c dynamic-memory-allocation


【解决方案1】:

由于这些线

char* buffer = (char*) malloc(16 * sizeof(char));
size_t allocated = 1;

对于前 4 次重新分配,程序会缩小 buffer。所以程序从i=16 开始写入未分配的内存,这是未定义的行为,所以任何事情都可能发生。这也很可能破坏内存管理,从而使realloc() 失败。

您可能希望将这两行更改为:

size_t allocated = 16; /* or = 1 if the 16 was a typo. */
char * buffer = malloc(allocated); 

其他说明:

参考最后一个注释,应应用以下修改

char * buffer = malloc(allocated); 

可能变成:

char * buffer = malloc(allocated); 
if (NULL == buffer)
{
  /* Error handling goes here. */
}

buffer = (char*) realloc(buffer, allocated * sizeof(char));

可能变成:

{
  char * pctmp = realloc(buffer, allocated);
  if (NULL == pctmp)
  {
    /* Error handling goes here. */
  }
  else
  {
    buffer = pctmp;
  }
}

【讨论】:

  • sizeof (char) 甚至基于 c99,因为它必须是 1 字节,所以你在哪里引用 sizeof (char) 总是 0?
  • @Zaibis: 哎哟 ...0 是一个错字。固定。
  • realloc 失败处理是一个常见的错误,使用相同的指针会导致泄漏:)
  • 现在,有了这个,我仍然有一个疑问:为什么只有当我没有调试它而不是持续崩溃时,该调用才会失败?
  • @RenanGemignani:你即将意识到未定义行为的非理性。
【解决方案2】:

评论多于答案,但我没有 50 分可评论。

这个:

char* buffer = (char*) malloc(16 * sizeof(char));

应该是

char* buffer = (char*) malloc(1 * sizeof(char));

allocated = 16.

【讨论】:

【解决方案3】:

我不知道,当你增加或减少 i。 但是我敢打赌,根据这个 sn-p,您的问题是:您无限地重新分配,并且由于您不检查 realloc 正在返回 NULL,这将使您的程序崩溃;)

正如已经说过的那样,即使是运行不佳的 pritf 也符合它,您违反了您的内存块。这将通过重新分配已在范围之外覆盖的内存地址来实现。(无论如何,它的 UB 除外)

或者,如果您尝试在无效的返回值时工作(返回 NULL 时会发生什么,因为您没有检查它会发生什么) 或者,如果您请求归零区域(大小参数为 0)并且您得到一个非零指针并且您使用该指针。 但是第二种情况可能不会发生在您的程序中;)

【讨论】:

    猜你喜欢
    • 2021-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多