sbrk(0)和sbrk(size)都返回相同的地址。

7
#include<unistd.h>
#include<stdio.h>

void *my_malloc(size_t size){
 void *p;
 void *q;
 p = sbrk(0);
 /* If sbrk fails, we return NULL */
 q = sbrk(size);
 if(q == (void *)-1){
  return NULL;
 }
 printf("\n size : %d  p : 0x%x q : 0x%x \n",size,p,q);
 return p;
}
int main(){
 int *p;
 p = my_malloc(5);
 printf("\n p : 0x%x \n",p);
}

brk(2)将断点放置在给定地址addr处,如果成功则返回0,否则返回-1。全局变量errno指示错误的性质。

sbrk(2)将断点移动给定的增量(以字节为单位)。根据系统实现的不同,它返回先前的或新的断点地址。失败时,它返回(void *)-1并设置errno。在某些系统上,sbrk接受负值(以释放一些映射内存)。

由于sbrk的规范没有确定其结果的含义,因此在移动断点时不使用返回值。但是,我们可以使用sbrk的一个特殊情况:当增量为零时(即sbrk(0)),返回的值是实际的断点地址(先前和新的断点地址相同)。因此,sbrk用于检索堆的开始位置,这是断点的初始位置。

因此,使用sbrk作为实现malloc的主要工具。

sbrk(0)以及sbrk(size)都返回相同的地址,我期望的是sbrk(size)应该返回比sbrk(0)多5个字节的地址。


你的实际问题是什么? - Paul R
1个回答

18

当您使用sbrk(0)时,您将获得当前的“断点”地址。

当您使用sbrk(size)时,您将获得前一个“断点”地址,即更改之前的地址。

因此,如果您先使用大小为零的调用,然后再使用正数大小的调用,则两者都将返回相同的值。如果在具有正数大小的调用之后再次使用大小为零的调用,它将返回地址。


2
您好,您可以解释一下什么是断点地址吗? - user1079065
@user1079065 我建议你阅读 Wikipedia 上关于sbrk的文章,它解释得非常清楚。 - Some programmer dude
我在手册中也读到了同样的内容,但措辞让我有点困惑:“成功时,sbrk() 返回先前的程序断点。(如果增加了断点,则该值是指向新分配内存开头的指针。)”新分配内存的开头与先前的断点地址相同。 - Lorenz Leitner
@Someprogrammerdude 我认为维基百科上有一个错误。 “成功完成后,brk子例程返回值为0,sbrk子例程返回程序中断前的值(如果增加了可用空间,则返回值指向新区域的开始)。如果没有成功,则返回值为-1,并设置errno全局变量以指示错误。”sbrk如何返回先前的值和新区域的起始位置。这没有意义。 - Sujay Phadke
@SujayPhadke 那个“if”改变了返回值的含义。sbrk返回一个东西,或者另一个东西。 - Some programmer dude
第二个if,是的。如果成功了,就不需要那个if了 - sbrk()在成功的情况下总是返回以前的断点。没错吧? - Sujay Phadke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接