0

我正在尝试在 NASM/x86 程序集中使用 sys_brk 分配一些内存。sys_break 返回break的新地址,是数据段的末尾吧?那么我新分配的内存在哪里呢?我假设它介于旧中断值和新中断值之间。因此,如果我使用 sys_brk 分配 64 字节的内存,我可以使用从调用 sys_brk 之前存储的旧中断值开始的接下来的 64 字节。我对吗?

我将分配内存的汇编代码看起来有点像这样。https://gist.github.com/nikAizuddin/f4132721126257ec4345

另一个问题是;

我应该在 Assembly 中编写一个函数,该函数返回指向动态分配内存的指针,并且该函数将从 C 程序中调用。如何从程序的 C 端释放这块内存?只调用 free() 就足够了吗?

4

1 回答 1

0

手册页(部分:C库brk(2)/内核 ABI 差异)描述了 glibc 包装器是如何在 Linux 的系统调用之上实现的,它在成功时返回新的 brk,或者在失败时返回旧的 brk。

据我了解,当前中断之外的内存未映射。当前中断以下的地址是数据段的一部分(在数据+bss+堆的意义上)。文档不清楚中断是否必须与页面对齐。(即您可以使用 sbrk(64),还是只能使用 sbrk(4096)?)

请参阅:brk() 系统调用是做什么的? 该问题的答案有一个使用 sbrk 替换 malloc 为 code-golf 的示例。所以是的,旧的休息是返回的地址。显然你可以sbrk增加任何你想要的,而不仅仅是页面。


您是编写内存分配器的人。 sbrk只是让您从操作系统中获得更多,mmap(MAP_ANONYMOUS)但不太灵活。 它不能帮助您跟踪空闲块,因此您可以将它们用于将来的分配,而不是总是从操作系统获得更多。

回馈您获得的内存的方法是使用否定参数sbrk进行调用。sbrk显然这需要后进先出的使用模式,这就是为什么 glibc 的 malloc 仅sbrk用于小分配(释放时可以放在 free-list 上,以供将来的 malloc 分发)。大分配最好立即返回给操作系统,而不是保持映射,因此 glibc 的 mallocmmap用于这些。

永远不要调用free(3)您没有从中获得的内存malloc(3)(或相关函数,例如strdup(3),在文档中说您可以并且应该free(3)使用内存。) IDK 如果您munmap在程序中断下方的内存页面上调用会发生什么。可能它会起作用,但是如果中断减少到那里,您可能会保留数据段,这可能会导致问题。


后来意识到这不是你要问的:

获取当前 brk 的最简单方法是简单地使用increment = 0.

这是 glibcmalloc(3)在内部所做的:

$ strace -e brk ls 2>&1 | m
brk(0)                                  = 0x650000
brk(0)                                  = 0x650000
brk(0x671000)                           = 0x671000

brk 手册页提到end(3). 显然有一些全局变量位于文本、数据和 bss 段的末尾。但是,&end程序中断只是“某处附近”,这就是为什么 malloc 仍然必须调用 sbrk(0) 才能获得初始中断。

于 2015-10-01T11:30:03.820 回答