关于brk / sbrk的不安全/遗留之处是什么?

时间:2019-03-26 23:50:42

标签: c malloc legacy sbrk brk

我在很多地方(音乐邮件列表,macOS论坛等)都听说brk()sbrk()是不安全的。这些地方中的许多要么根本不给出解释,要么给出非常模糊的解释。例如,this链接指出“这些功能从根本上被破坏了”,并继续说mallocsbrk子系统被彻底破坏了,它们破坏了堆,等等。

我的问题是:为什么会这样?如果使用malloc来分配sbrk足够大的内存块,以平息或实质上减少了进一步分配的需要,那么sbrk和{{ 1}}使用起来安全吗?

这是我对brksbrk的实现:

brk

sbrk

#include <unistd.h> #include <stddef.h> void *sbrk(intptr_t inc) { intptr_t curbrk = syscall(SYS_brk, NULL); if( inc == 0 ) goto ret; if( curbrk < 0 ) return (void *)-1; curbrk((void *)(curbrk+inc)); ret: return (void *)curbrk; }

brk

1 个答案:

答案 0 :(得分:3)

现实高度依赖于实现,但这是一些要素:

不安全

发明了

brk / sbrk来允许进程从系统请求更多内存,并在单个连续段中释放它。这样,它们被许多mallocfree实现使用。问题在于,当它返回一个唯一的段时,由于(同一过程的)多个模块直接使用它,会出错。由于竞争条件,在多线程进程中情况变得更糟。假设有2个线程想要添加新的内存。他们将使用sbrk(0)查看当前的最高地址,看到相同的地址,使用brksbrk请求新的内存,并且由于竞争条件,它们都将使用相同的内存

即使在单线程进程中,某些mallocfree实现也假定只允许它们使用低级s/brk接口,并且其他任何代码也应使用它们。在这种情况下,如果内部保留的中断片段的图像不再是假定值,那么事情将会出错。他们应该猜测该段的某些部分被“保留”用于其他用途,可能会破坏释放任何内存的能力。

因此,用户代码永远不要直接使用brk / sbrk,而只能依靠malloc / free。当且仅当您正在编写包含malloc / realloc / calloc / free的标准库的实现时,才能安全地使用brk / sbrk

旧版

在现代系统上,mmap可以更好地使用虚拟内存管理。您可以根据需要使用任意数量的动态内存段,而无需它们之间的交互。因此,在现代系统上,除非您特别需要使用brk / sbrk进行内存分配,否则应使用mmap

便携性

brksbrk的FreeBSD参考说明:

  

brk()和sbrk()函数是自     现代虚拟内存管理的出现。

及更高版本:

  

错误:     将brk()或sbrk()与malloc(3),free(3)或类似函数混合使用     导致程序无法移植。