使用realloc是否安全?

k3o*_*3oy 14 c memory-leaks memory-management realloc

前段时间我的一位朋友告诉我不要使用realloc,因为它不安全,但他不能告诉我为什么,所以我对这个问题进行了一些研究,最接近我怀疑的是:
https://buildsecurityin.us -cert.gov/bsi/articles/knowledge/coding/809-BSI.html
http://www.iso-9899.info/wiki/Why_not_realloc
我想知道我是否可以继续在我的代码中使用realloc或者如果它是不安全有没有其他方法来重新分配内存?感谢您的关注.

Dav*_*nan 24

使用起来非常安全realloc.这是在C程序中重新分配内存的方法.

但是,您应该始终检查错误条件的返回值.不要陷入这个常见陷阱:

p = realloc(p, new_size); // don't do this!
Run Code Online (Sandbox Code Playgroud)

如果失败,则realloc返回NULL并且您无法访问p.而是这样做:

new_p = realloc(p, new_size);
if (new_p == NULL)
    ...handle error
p = new_p;
Run Code Online (Sandbox Code Playgroud)


Fle*_*exo 14

两篇相关文章中的第一篇提出了两项​​投诉,超出了"检查呼叫成功"这一点已经提出的要点.

完成此操作后,旧内容将被丢弃并留在内存中.对于清除所有数据痕迹很重要的安全内存应用程序,此行为是不合适的.

如果您碰巧存储敏感数据(例如私钥,未散列(!)密码等)并且想要使攻击更难以恢复系统上的数据或其他进程以窃取数据,这是一个有效点.

由于它会移动内存,因此任何指向该内存的旧指针都会变为无效,并可能导致程序崩溃或行为异常.

这一点对我来说似乎是无稽之谈.他们提出的解决方案并不是更好,他们malloc(),复制,然后free()原始具有相同的净效果 - 地址已经改变.如果你想避免移动内存,你可能可以使用一些特定于平台的调用来做到这一点,如果你安排在它们附近有足够的空闲地址空间.如果您事先知道要预留多少地址空间,那么您可能不会考虑realloc()先调用!

如果你赌博realloc()从来没有移动,总是在成长,那么无论如何你可能会有更大的问题需要担心,切换到malloc()+ copy + free()无法解决这个问题.


除了"正确检查您的返回值"之外,第二篇文章中最有趣的一点是警告:

不要一次将缓冲区重新分配1个字节.

他们警告说:

这可以保证搅乱你的内存堆

这是一个潜在的有效点,但它不是对realloc()自己的批评; 如果使用malloc()+ copy +,也会发生同样的情况free().真正的解决方案是合理地增加缓冲区,无论你如何成长或更好,然后预先分配正确大小的块.

他们也有一点关注

使用realloc将内存返回给系统.

他们在这里是正确的,使用0以外的任何大小可能实际上不会返回.它可能使事情变得更糟,但这种用法似乎仍然是过早"优化"的一个例子.再次修复是使用合理大小的分配开始.

排序答案:它不是不安全的,但它也不是解决所有问题的神奇方法.


Jer*_*fin 6

realloc本身是安全的,但使用它安全是有点棘手-给我说,使用它是我见过的代码大约85-90%的点这样做的安全.问题是realloc返回NULL表示失败 - 但是当它这样做时,您作为输入提供的指针仍然有效(前提是您没有将其分配大小调整为0).

因此,realloc当且仅当realloc返回非空指针时,必须将返回值分配给作为输入提供的指针.如果它返回空指针,则前一个指针有效,但未调整分配大小.

另请注意,许多人认为realloc放大分配时只能失败和/或移动分配.实际上,它可能会失败(虽然这不太可能)或者将数据移动到不同的位置(更有可能),即使您正在减少分配大小.