1

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

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

我正在使用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;
}
4

3 回答 3

4

由于这些线

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

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

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

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

其他注意事项:

  • sizeof(char)总是1
  • 不要投射结果,malloc/calloc/realloc因为没有必要也不推荐:https ://stackoverflow.com/a/605858/694576 。
  • 请检查系统调用的结果。

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

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;
  }
}
于 2013-08-20T15:20:38.893 回答
1

更多的是评论而不是答案,但我没有 50 分可评论。

这个:

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

应该

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

或者

allocated = 16.
于 2013-08-20T15:25:13.803 回答
0

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

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

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

于 2013-08-20T15:22:32.007 回答