根据Linux程序员手册:

Brk()和sbrk()改变程序中断的位置 定义进程数据段的结束。

这里的数据段是什么意思?它只是数据段还是数据、BSS和堆的组合?

根据维基数据段:

有时数据、BSS和堆区域被统称为“数据段”。

我认为没有理由只改变数据段的大小。如果它是数据,BSS和堆,那么它是有意义的,因为堆将获得更多的空间。

这就引出了我第二个问题。到目前为止,在我读过的所有文章中,作者都说堆向上增长,堆栈向下增长。但是他们没有解释当堆占用了堆和栈之间的所有空间时会发生什么?


当前回答

堆放在程序数据段的最后。Brk()用于改变(扩展)堆的大小。当堆不能再增长时,任何malloc调用都将失败。

其他回答

我可以回答你的第二个问题。Malloc将失败并返回一个空指针。这就是为什么在动态分配内存时总是检查空指针。

Malloc使用BRK系统调用来分配内存。

包括

int main(void){

char *a = malloc(10); 
return 0;
}

用strace运行这个简单的程序,它将调用BRK系统。

堆放在程序数据段的最后。Brk()用于改变(扩展)堆的大小。当堆不能再增长时,任何malloc调用都将失败。

您可以自己使用brk和sbrk来避免每个人都在抱怨的“malloc开销”。但是您不能轻易地将此方法与malloc结合使用,因此它仅适用于不需要释放任何东西的情况。因为你不能。另外,应该避免任何可能在内部使用malloc的库调用。Ie。斯特伦可能安全,但fopen可能就不安全了。

调用sbrk就像调用malloc一样。它返回一个指向当前断点的指针,并使该断点增加该值。

void *myallocate(int n){
    return sbrk(n);
}

虽然不能释放单个的分配(因为没有malloc开销,记住),但是可以通过使用第一次调用sbrk返回的值调用brk来释放整个空间,从而使brk返回。

void *memorypool;
void initmemorypool(void){
    memorypool = sbrk(0);
}
void resetmemorypool(void){
    brk(memorypool);
}

您甚至可以堆叠这些区域,通过将换行符倒回到区域的开始位置来丢弃最近的区域。


还有一件事……

SBRK在code golf中也很有用,因为它比malloc短2个字符。

数据段是内存中保存所有静态数据的部分,在启动时从可执行文件读取,通常为零填充。