realloc和缓冲区溢出

6
为什么result似乎没有被重新分配?
  while (loc) {
    char nextLine[MAX_PATH_LEN + 30];
    sprintf(nextLine, "%s:%d\n", loc->item.pathname, loc->item.offset);
    DPRINTF('h', ("got next line\n"));
    while (spaceUsedUp + strlen(nextLine) > allocatedSize) {
      allocatedSize *= 2;
    }
    if (realloc(result, allocatedSize) == NULL) {
      perror("realloc");
    }
    DPRINTF('h', ("Next line length is %d\n", strlen(nextLine)));
    DPRINTF('h', ("Allocated size is %d\n", allocatedSize));
    DPRINTF('h', ("The size of the result is %d\n", strlen(result)));

    strcat(result, nextLine); // THIS LINE CAUSES THE BUFFER OVERFLOW                         

    spaceUsedUp += strlen(nextLine);
    DPRINTF('h', ("SpaceUsedUp is %d\n", spaceUsedUp));
    loc = loc->nextLocation;
  }

输出结果如下:
got next line
Next line length is 21
Allocated size is 100
The size of the result is 0
SpaceUsedUp is 21
got next line
Next line length is 21
Allocated size is 100
The size of the result is 21
SpaceUsedUp is 42
got next line
Next line length is 21
Allocated size is 100
The size of the result is 42
SpaceUsedUp is 63
got next line
Next line length is 21
Allocated size is 100
The size of the result is 63
SpaceUsedUp is 84
got next line
Next line length is 21
Allocated size is 200
The size of the result is 84
*** buffer overflow detected ***: ./proj3/disksearch terminated
4个回答

7
您正在丢弃realloc返回的结果。您需要将该值赋给“result”。典型用法如下:
if ((tmp = realloc(result, allocatedSize)) == NULL) {
      perror("realloc");
      /* more error handling here, including (usually) freeing result or exiting */
} else {
      result = tmp;
}

5

realloc函数返回重新分配的缓冲区的指针,并可能释放原始缓冲区。这意味着:

if (realloc(result, allocatedSize) == NULL)

这段代码有问题,因为它实际上丢弃了缓冲区,让你使用旧的、现在可能被释放的缓冲区。你看到的问题不是缓冲区溢出,而是由于尝试写入你不再拥有分配的内存而导致的未定义行为引起的崩溃。

你可以修改你的代码为

void* tmp = realloc(result, allocatedSize);
if (tmp != NULL)
    result = tmp;
else    
    perror("realloc");

1
如果realloc出现错误,这将导致内存泄漏,因为result的原始值现在已经丢失。 - William Pursell
@WilliamPursell 我不明白我的修改有什么问题。你在哪里看到内存泄漏了?还是你的意思是OP的代码正在泄漏重新分配的缓冲区? - simonc
1
这与以下问题相同:result = malloc(...); result = NULL。如果realloc出错,您需要跟踪result中的旧值。(尽管通常会执行exitfree操作。) - William Pursell
哎呀,我明白你的意思了。谢谢,现在已经修复了。 - simonc

0

我喜欢man页面,所有生活的答案都在那里... 至少是重要的答案。

返回值
malloc() 和 calloc() 函数返回一个指针,该指针指向适用于任何类型变量的内存,并进行了适当的对齐。发生错误时,这些函数返回 NULL。成功调用 malloc() 并使用大小为零的大小或成功调用 calloc() 并使用 nmemb 或 size 等于零也可以返回 NULL。 free() 函数没有返回值。

realloc() 函数返回一个指向新分配的内存的指针,该内存适用于任何类型的变量并且可能与 ptr 不同,或者如果请求失败,则返回 NULL。如果大小等于 0,则返回 NULL 或适合传递给 free() 的指针。如果 realloc() 失败,则原始块保持不变;它不会被释放或移动。

正如您所看到的,malloc() 的朋友 realloc() 只能在 man 页面中得到一个条目,因为高亮部分所示 realloc() 返回的值可能与传入的内存引用不同。这是一个重要的说明。

所以在你的代码中:

if (realloc(result, allocatedSize) == NULL) {
  perror("realloc");
}

你正在忽略你真正关心的结果。检查 NULL 是好的,但你需要赋值给某个临时变量,然后再进行检查。 (请注意,将结果分配给临时变量的原因也在 man 页面中说明,如果 realloc() 失败,则只要不覆盖它,你的 result 缓冲区仍然是可用的)

0

realloc() 的返回类型是 void*,它被转换为所需的类型。这个指针指向新分配大小的内存。理想情况下,realloc 执行四个操作:

  1. 创建指定大小的新内存。
  2. 将旧内存中的内容复制到新内存中。
  3. 释放旧内存。
  4. 返回新内存的地址。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接