C++可变内存分配

发布于 2024-10-30 02:08:11 字数 401 浏览 1 评论 0原文

这些主要是编译器设计问题。当你的编译器编译它时,例如:

int * pData = new int[256];

内存是如何动态分配的?编译器是否调用为您分配内存的操作系统例程,或者编译为您分配内存的函数?

另外,当您编写如下内容时:

if (x == 5)
    int y;

由于内存不是在运行时分配的,因此我假设数据占用了程序数据段中的一些空间。由于编译器无法真正确定 int y; 分支是否会在运行时执行,因此无论 int y; 是否为变量,是否会保留内存被处决?如果无论如何都保留它,那么 mem 分配可能会或可能不会执行的块中的任何变量不是更节省内存吗?

噢,谢谢

These are mostly compiler design questions. When your compiler compiles this, for example:

int * pData = new int[256];

How is the memory allocated on-the-fly? Does the compiler make a call to an OS routine that allocates memory for you or is a function compiled that allocates the memory for you?

Also, when you write something like this:

if (x == 5)
    int y;

Since the memory is not allocated at runtime, I'm assuming that the data takes up some room in the data segment of the program. Since the compiler can't really determine whether or not the int y; branch will be executed at runtime, is the memory reserved for the variable whether or not int y; is executed? And if it's reserved regardless, isn't it more memory-efficient to mem alloc any variables that are in a block that may or may not be executed?

o.o thanks

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

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

发布评论

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

评论(7

娇纵 2024-11-06 02:08:11

对于第一个问题:当编译器遇到 new 运算符(如您的示例中所示)时:

int * pData = new int[256];

它有效地发出如下所示的代码:

int *pData = reinterpret_cast<int*>(::operator new(256 * sizeof(int)));
// the compiler may also choose to reserve extra space here or elsewhere to
// "remember" how many elements were allocated by this new[] so delete[] 
// can properly call all the destructors too!

如果应该调用构造函数,则也会发出(在这个例子中,我相信没有调用构造函数)。

operator new(std::size_t) 是一个由标准库实现的函数,通常但并非总是,它会归结为 malloc< /代码> 调用。

malloc 必须进行系统调用,以从操作系统。由于操作系统分配器通常使用较大的固定大小的内存块,因此 malloc 不会每次都进行此调用,只有在耗尽当前拥有的内存时才会进行此调用。


对于第二个问题:对于局部变量,这实际上取决于编译器。该标准没有提及堆栈。但是,您很可能使用通用架构,运行通用操作系统并使用通用编译器:-)。

因此,对于常见情况,编译器通常会在函数调用开始时为所有局部变量保留空间,方法是相应地调整堆栈或为它们保留寄存器(如果可以的话)(寄存器是首选)因为它快得多)。

然后(在c++中),当遇到变量时,它会调用构造函数。理论上,它可以根据需要调整堆栈,但要证明正确性会很复杂,而且效率较低。通常,保留堆栈空间是一条指令,因此一次完成所有操作是非常理想的。

For the first question: When the new operator is encounter by the compiler like in your example:

int * pData = new int[256];

It effectively emits code which looks like this:

int *pData = reinterpret_cast<int*>(::operator new(256 * sizeof(int)));
// the compiler may also choose to reserve extra space here or elsewhere to
// "remember" how many elements were allocated by this new[] so delete[] 
// can properly call all the destructors too!

If a constructor should be called, that is emitted as well (in this example, no constructor is called I believe).

operator new(std::size_t) is a function which is implemented by the standard library, often, but not always, it will boil down to a malloc call.

malloc will have to make a system call, to request memory from the OS. Since OS allocators usually work with larger fixed sized blocks of memory, malloc will not have make this call every time, only when it has exhausted the memory it currently has.


For the second question: For local variables, it really is up to the compiler. The standard makes no mention of a stack. However, most likely you are on a common architecture running a common OS and using a common compiler :-).

So for the common case, the compiler will typically reserve space at the beginning of the function call for all local variables by adjusting the stack accordingly or reserving registers for them if it can (a register being the preferred choice since it is much faster).

Then (in c++), when the variable is encountered, it will call the constructor. It could in theory, adjust the stack on an as needed basis, but this would be complicated to prove correct and less efficient. Typically reserving stack space is a single instruction, so doing it all at once is pretty optimal.

独孤求败 2024-11-06 02:08:11

内存是如何动态分配的?编译器是否调用为您分配内存的操作系统例程,或者编译为您分配内存的函数?

在大多数实现中,它是这两者的结合。通常有一个操作系统服务用于向您的进程提供内存块,并且运行时或标准库中也有一些代码在您的应用程序内以更细粒度的方式管理这些内存块。

是为变量保留的内存,无论是否为“int y;”被执行?如果无论如何都保留它,那么内存分配可能会或可能不会执行的块中的任何变量不是更节省内存吗?

通常情况下,不会 - 仅当执行适当的代码时才会分配 y 的空间。具有自动存储类别的变量通常位于堆栈上,因此为它们腾出空间就像修改堆栈指针一样简单。也就是说,在这种情况下,编译器几乎可以做任何它想做的事情,因此检查工具链的输出是确定的唯一方法。

How is the memory allocated on-the-fly? Does the compiler make a call to an OS routine that allocates memory for you or is a function compiled that allocates the memory for you?

In most implementations, it's a bit of a combination of those two. There is normally an operating system service that is used to provide blocks of memory to your process, and also some code in the runtime or the standard library that manages those blocks of memory on a finer-grained scale inside your application.

is the memory reserved for the variable whether or not "int y;" is executed? And if it's reserved regardless, isn't it more memory-efficient to mem alloc any variables that are in a block that may or may not be executed?

Normally, no - the space for y would be allocated only if the appropriate code were executed. Variables with automatic storage class are normally on the stack, so making space for them is as easy as modifying the stack pointer. That said, the compiler can do pretty much whatever it wants in this case, so inspecting the output from your toolchain is the only way to know for sure.

此生挚爱伱 2024-11-06 02:08:11

局部变量 (int y) 在堆栈上分配。

指针也是如此,但是“new”表达式是在堆上分配的,通​​常是通过某种 malloc 调用。确切的方法和堆布局是实现定义的。

数据段中只有全局静态数据。

示例 int y 将被优化掉,因为它未被使用。

与 C# 等不同,C++不允许减少变量的范围,因此将短命的局部变量包装在 { SomeClass y;可以帮助,所以它会更早被破坏

但是,我很确定对于简单类型(如 int)不存在这样的限制,因为这些类型永远不会有析构函数

Local variables (int y) are allocated on the stack.

The same thing goes for the pointer, however the 'new'-ed expression is allocated on the heap, usually through a malloc call of sorts. The exact method and heap layout are implementation-defined.

Only global static data are in the data-segment.

The example int y will be optimized out because it isn't used.

Unlike e.g. C#, C++ is not allowed to reduce the scope for a variable so wrapping a shortlived local in { SomeClass y; } could help, so it gets destructed earlier

However, I'm pretty sure that for simple types (like int) no such restriction exists, because there can never be a destructor for those

看透却不说透 2024-11-06 02:08:11

关于你的第二个问题,条件代码中的变量是自动变量。通常这些是在堆栈上分配的。在这种情况下,一个好的编译器会注意到它永远不会被读取或写入,甚至不会为它在堆栈上分配空间。

With regards to your second question, that variable in the conditional code is an automatic variable. Generally those are allocated on the stack. In this case a good compiler would notice it is never read from or written to and not even bother allocating space on the stack for it.

牛↙奶布丁 2024-11-06 02:08:11

这实际上取决于第二个示例的编译器,这就是为什么我们有 volatile 关键字(如果我们将变量映射到发生变化的地址),或者它可能只是给你一个警告,但我相当确定它将把它包含到你的程序中(有时您出于黑客原因想要增加方法的堆栈大小)。第一个示例本质上调用 malloc(256 * sizeof(int)) 并返回指向该段的指针。

It really depends on the compiler for the 2nd example which is why we have the volatile keyword (in case we map variables to addresses which change) or it might just give you a warning but I'm fairly certain it will include it into your program (sometimes you want to increase the stack size of your method for hackish reasons). The first example in essence calls malloc(256 * sizeof(int)) and returns a pointer to that segment.

白色秋天 2024-11-06 02:08:11

情况1:它将调用操作系统例程在堆上分配内存。操作系统管理内存。

情况2:这是在堆栈上分配的。堆栈已预先分配给您的进程,用于局部变量和函数参数。

Case 1: it will call an OS routine to allocate memory on the heap. The OS manages the memory.

Case 2: this is allocated on the stack. The stack is preallocated to your process and is used for local variables and functions arguments.

哀由 2024-11-06 02:08:11

对于第一个问题:

编译器生成代码来调用函数operator new,该函数本身通常从C运行时库调用malloc,而C运行时库本身调用一些特定于操作系统的库(您可以看到它的去向)在某个时刻最终会切换到内核模式并为进程分配内存。

无论如何,编译器为您自己的程序生成的本机代码本身不会进行分配。

对于第二个问题:

int y的内存是在堆栈上分配的。无论条件是否为真,在最简单的非优化情况下,每次控制进入函数时都会发生堆栈空间分配。

由于堆栈分配只是一些寄存器操作,无论要分配多少空间,这些操作都需要相同的时间,而且一旦函数返回,内存就会被回收,所以这里不存在“内存占用”问题。

For the first question:

The compiler generates code to call the function operator new, which itself usually calls malloc from the C runtime library, which itself makes a call to some OS-specific library which (you can see where this is going) at some point ends up switching into kernel mode and allocating memory for the process.

In any case, the native code which the compiler generates for your own program does not make the allocation itself.

For the second question:

The memory for int y is allocated on the stack. Regardless of whether the condition is true, in the simplest, non-optimizing case the stack space allocation will happen each and every time control enters your function.

Since stack allocation is just a few register operations that take the same time no matter how much space is to be allocated, and since the memory will be reclaimed as soon as your function returns, there is no "memory hog" problem here.

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