当你调用realloc()
时,你应该在将返回的指针指向作为参数传递给函数的指针之前检查函数是否失败...
我一直遵循这条规则。
当您确定内存将被截断而不是增加时,是否有必要遵循此规则?
我从来没有见过它失败过。只是想知道我是否可以保存一些指令。
答案 0 :(得分:7)
realloc
可以自行决定将块复制到新地址,无论新大小是大还是小。如果malloc
实现需要新的分配来“缩小”存储块(例如,如果新的大小需要将存储块放在不同的分配池中),则这可能是必要的。这在glibc
documentation中注明:
在几个分配实现中,将块缩小有时需要复制它,因此如果没有其他可用空间,它可能会失败。
因此,即使收缩,您也必须始终检查realloc
的结果。 realloc
可能无法缩小块,因为它无法同时分配新的较小块。
答案 1 :(得分:4)
即使你realloc
(仔细阅读realloc(3)和Posix realloc请求)到较小的尺寸,基础实现也相当于malloc
(新的较小尺寸),然后是memcpy
(从旧区到新区),然后是free
(旧区域)。或者它可能什么都不做......(例如,因为一些粗略的malloc
实施保持一组有限的尺寸 - 就像2的2倍或3倍的功率 - 并且旧的和新的尺寸要求适合相同的尺寸....)
malloc
可能会失败。所以realloc
仍然可能失败。
实际上,由于这个原因,我通常不建议使用realloc
:只需自己执行malloc
,memcpy
,free
。
实际上,像malloc
这样的动态堆内存函数很少会失败。但是当他们这样做时,如果你不处理,可能会发生混乱。在Linux和其他一些Posix系统上,您可以setrlimit(2)使用RLIMIT_AS
-e.g.使用bash ulimit
内置 - 降低测试目的的限制。
您可能想要研究C memory management的源代码实现。例如MUSL libc(对于Linux)是非常易读的代码。在Linux上,malloc
通常构建在mmap(2)之上(C库可以使用mmap
分配大块内存,然后管理其中较小的已使用和已释放的内存区域。)