sbrk() 在 C++ 中如何工作?

发布于 2024-08-17 16:39:15 字数 194 浏览 11 评论 0 原文

在哪里可以阅读有关 sbrk() 的详细信息?

它究竟是如何运作的?

在什么情况下我想使用 sbrk() 而不是繁琐的 malloc()new()

顺便说一句,sbrk() 的扩展是什么?

Where can I read about sbrk() in some detail?

How does it exactly work?

In what situations would I want to use sbrk() instead of the cumbersome malloc() and new()?

btw, what is the expansion for sbrk()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

埖埖迣鎅 2024-08-24 16:39:16

您已经标记了这个 C++,那么为什么要使用“麻烦的”malloc() 而不是 new 呢?无论如何,我不确定 malloc 有何麻烦;在内部也许是这样,但你为什么要关心呢?如果您确实关心(例如出于确定性的原因),您可以分配一个大池并为该池实现您自己的分配器。当然,在 C++ 中,您可以重载 new 运算符来执行此操作。

sbrk 用于将 C 库粘合到底层系统的操作系统内存管理。因此,进行操作系统调用而不是使用 sbrk()。至于它如何工作,那是依赖于系统的。例如,如果您使用 Newlib C 库(通常在带有 GNU 编译器的“裸机”嵌入式系统上使用),则必须 自己实现 sbrk,因此它在这些情况下如何工作取决于您,只要它实现了扩展堆或失败所需的行为。

正如您从链接中看到的,它没有做太多事情,并且直接使用会非常麻烦 - 您可能最终会将其包装在 malloc 和 new 无论如何提供的所有功能中。

You've tagged this C++ so why would you use 'cumbersome' malloc() rather than new? I am not sure what is cumbersome about malloc in any case; internally maybe so, but why would you care? And if you did care (for reasons of determinism for example), you could allocate a large pool and implement your own allocator for that pool. In C++ of course you can overload the new operator to do that.

sbrk is used to glue the C library to the underlying system's OS memory management. So make OS calls rather than using sbrk(). As to how it works, that is system dependent. If for example you are using the Newlib C library (commonly used on 'bare-metal' embedded systems with the GNU compiler), you have to implement sbrk yourself, so how it works in those circumstances is up to you so long as it achieves its required behaviour of extending the heap or failing.

As you can see from the link, it does not do much and would be extremely cumbersome to use directly - you'd probably end-up wrapping it in all the functionality that malloc and new provide in any case.

没︽人懂的悲伤 2024-08-24 16:39:16

这取决于您所说的 malloc“麻烦”是什么意思。 sbrk 通常不再直接使用,除非您正在实现自己的内存分配器:IE,运算符覆盖“new”。即使这样,我也可能会使用 malloc 来提供我的初始记忆。

如果您想了解如何在 sbrk() 之上实现 malloc(),请查看 http://web.ics.purdue.edu/~cs354/labs/lab6/ 这是一个练习。

不过,在现代系统上,您不应该触摸此界面。由于您调用 malloc 和 new 很麻烦,我怀疑您不具备在代码中安全、正确使用 sbrk 所需的所有经验。

This depends on what you mean by malloc being "Cumbersome". sbrk is typically not used directly anymore, unless you're implementing your own memory allocator: IE, operator overriding "new". Even then I'd possibly use malloc to give me my initial memory.

If you'd like to see how to to implement malloc() on top of sbrk(), check out http://web.ics.purdue.edu/~cs354/labs/lab6/ which is an exercise going through that.

On a modern system you shouldn't touch this interface, though. Since you're calling malloc and new cumbersome, I suspect you don't have all the requisite experience to safely and properly use sbrk for your code.

浅浅 2024-08-24 16:39:15

查看brk/sbrk 的规范

该调用基本上要求操作系统通过将先前的“中断值”增加一定量来为应用程序分配更多内存。该数量(第一个参数)是您的应用程序获得的额外内存量。

大多数基本的 malloc 实现都建立在 sbrk 系统调用之上,以获取它们分割和跟踪的内存块。 mmap 函数通常被认为是更好的选择(这就是为什么像 dlmalloc 这样的 malloc 都支持 #ifdef)。

至于“它是如何工作的”,sbrk在其最简单的级别可能看起来像这样:

uintptr_t current_break; // Some global variable for your application.
                         // This would probably be properly tracked by the OS for the process
void *sbrk(intptr_t incr)
{
    uintptr_t old_break = current_break;
    current_break += incr;
    return (void*) old_break;
}

现代操作系统会做更多的事情,例如将页面映射到地址空间并为每个页面添加跟踪信息分配的内存块。

Have a look at the specification for brk/sbrk.

The call basically asks the OS to allocate some more memory for the application by incrementing the previous "break value" by a certain amount. This amount (the first parameter) is the amount of extra memory your application then gets.

Most rudimentary malloc implementations build upon the sbrk system call to get blocks of memory that they split up and track. The mmap function is generally accepted as a better choice (which is why mallocs like dlmalloc support both with an #ifdef).

As for "how it works", an sbrk at its most simplest level could look something like this:

uintptr_t current_break; // Some global variable for your application.
                         // This would probably be properly tracked by the OS for the process
void *sbrk(intptr_t incr)
{
    uintptr_t old_break = current_break;
    current_break += incr;
    return (void*) old_break;
}

Modern operating systems would do far more, such as map pages into the address space and add tracking information for each block of memory allocated.

若能看破又如何 2024-08-24 16:39:15

sbrk 已经过时了,现在您可以使用 mmap 将某些页面映射到 /dev/zero 之外。它当然不是您用来代替 malloc 和朋友的东西,它更多的是实现这些的一种方法。当然,它只存在于基于 posix 的操作系统上,这些操作系统关心对古代代码的向后兼容性。

如果您发现 Malloc 和 New 太麻烦,您应该考虑垃圾收集...但要注意,这会带来潜在的性能成本,因此您需要了解自己在做什么。

sbrk is pretty much obsolete, these days you'd use mmap to map some pages out of /dev/zero. It certainly isn't something you use instead of malloc and friends, it's more a way of implementing those. Also, of course, it exists only on posix-based operating systems that care about backwards compatibility to ancient code.

If you find Malloc and New too cumbersome, you should look into garbage collection instead... but beware, there is a potential performance cost to that, so you need to understand what you are doing.

迷乱花海 2024-08-24 16:39:15

您永远不想使用 sbrk 代替 mallocfree。它是不可移植的,通常仅由标准 C 库的实现者或在它不可用的情况下使用。它在手册页中描述得非常好:

描述

brk() 设置结束
数据段到指定的值
end_data_segment,当该值为
合理,系统确实有
内存足够,但进程没有
超过其最大数据大小(请参阅
setrlimit(2))。

sbrk() 增加程序的数据
空间增量字节。 sbrk() 不是
一个系统调用,它只是一个C库
包装纸。调用 sbrk() 并使用
增量为 0 可以用来求
程序中断的当前位置。

返回值

成功后,brk() 返回
零,sbrk() 返回一个指向
新区域的开始。出错时,
返回-1,并将 errno 设置为 ENOMEM。

最后,mallocfree 并不麻烦 - 它们是 C 中分配和释放内存的标准方法。即使您想实现自己的内存分配器,最好只需使用 mallocfree 作为基础 - 一种常见的方法是使用 malloc 一次分配一个大块,并从中提供内存分配(这就是子分配器或池通常实现的)


关于名称 sbrk (或其表兄弟 brk)的起源,它可能与以下事实有关:堆的末尾由称为“break”的指针标记。堆在 BSS 段之后开始,通常朝堆栈方向增长。

You never want to use sbrk instead of malloc or free. It is non-portable and is typically used only by implementers of the standard C library or in cases where it's not available. It's described pretty well in its man page:

Description

brk() sets the end of the
data segment to the value specified by
end_data_segment, when that value is
reasonable, the system does have
enough memory and the process does not
exceed its max data size (see
setrlimit(2)).

sbrk() increments the program's data
space by increment bytes. sbrk() isn't
a system call, it is just a C library
wrapper. Calling sbrk() with an
increment of 0 can be used to find the
current location of the program break.

Return Value

On success, brk() returns
zero, and sbrk() returns a pointer to
the start of the new area. On error,
-1 is returned, and errno is set to ENOMEM.

Finally,malloc and free are not cumbersome - they are the standard way to allocate and release memory in C. Even if you want to implement your own memory allocator, it's best to just use malloc and free as the basis - a common approach is to allocate a large chunk at a time with malloc and provide memory allocation from it (this is what suballocators, or pools, usually implement)


Re the origin of the name sbrk (or its cousin brk), it may have something to do with the fact that the end of the heap is marked by a pointer known as the "break". The heap starts right after the BSS segments and typically grows up towards the stack.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文