根据Linux程序员手册:
Brk()和sbrk()改变程序中断的位置 定义进程数据段的结束。
这里的数据段是什么意思?它只是数据段还是数据、BSS和堆的组合?
根据维基数据段:
有时数据、BSS和堆区域被统称为“数据段”。
我认为没有理由只改变数据段的大小。如果它是数据,BSS和堆,那么它是有意义的,因为堆将获得更多的空间。
这就引出了我第二个问题。到目前为止,在我读过的所有文章中,作者都说堆向上增长,堆栈向下增长。但是他们没有解释当堆占用了堆和栈之间的所有空间时会发生什么?
根据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个字符。
数据段是内存中保存所有静态数据的部分,在启动时从可执行文件读取,通常为零填充。