仅在未调试时多次调用后realloc失败

时间:2013-08-20 15:13:12

标签: c dynamic-memory-allocation

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

我的项目的许多其他部分都有非常相似的代码,具有相同的内存分配策略和调用(仅更改void*我传递给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;
}

3 个答案:

答案 0 :(得分:3)

由于这些行

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); 

其他说明:

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

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;
  }
}

答案 1 :(得分:1)

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

此:

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

应该是

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

allocated = 16.

答案 2 :(得分:0)

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

正如已经说过的那样,即使是运行不好的pritf也符合它,你的内存也会受到侵犯。这将通过重新分配已被覆盖范围之外的内存地址来实现(除了其UB之外)

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