C和C++如何在堆栈上存储大对象?

24 浏览
0 Comments

C和C++如何在堆栈上存储大对象?

我正在试图弄清楚C和C++如何在栈上存储大对象。通常,栈的大小是一个整数,所以我不明白更大的对象是如何存储在其中的。它们是否只是占用多个栈“槽位”?

0
0 Comments

C和C++如何在堆栈上存储大型对象?

堆栈是一块内存。堆栈指针指向堆栈的顶部。可以将值推入堆栈并弹出以检索它们。

例如,如果我们有一个使用两个参数(一个字节大小和另一个2字节大小)调用的函数(假设我们有一个8位PC)。

这两个参数都被推入堆栈,这将使堆栈指针上移:

03: par2 byte2
02: par2 byte1
01: par1

现在函数被调用,返回地址被放在堆栈上:

05: ret byte2

04: ret byte1

03: par2 byte2

02: par2 byte1

01: par1

好了,现在函数内部有两个局部变量;一个占用2个字节,另一个占用4个字节。对于这些变量,堆栈上保留了一个位置,但首先我们保存堆栈指针,以便通过向上计数找到变量的起始位置,通过向下计数找到参数。

11: var2 byte4

10: var2 byte3

09: var2 byte2

08: var2 byte1

07: var1 byte2

06: var1 byte1

---------

05: ret byte2

04: ret byte1

03: par2 byte2

02: par2 byte1

01: par1

正如您所看到的,只要还有剩余空间,您可以将任何内容放入堆栈中。否则,您将会遇到导致这个问题出现的现象。

0
0 Comments

C和C++在堆栈上存储大对象时可能会遇到问题。通常,pushpop指令不用于存储局部堆栈帧变量。在函数的开头,通过将堆栈指针减去函数的局部变量所需的字节数(对齐到字大小),来设置堆栈帧。这样可以为这些值在堆栈上分配相应的空间。然后,所有局部变量都通过指向该堆栈帧的指针(在x86上为ebp)来访问。

然而,对于大对象,将其分配在堆栈上可能会导致堆栈溢出。由于堆栈的大小是有限的,当分配给大对象的空间超过堆栈的容量时,就会发生堆栈溢出错误。

为了解决这个问题,可以使用堆来动态分配大对象的内存。通过使用new运算符(在C++中)或malloc函数(在C中),可以在堆上分配内存。这样,大对象将不再存储在堆栈上,而是存储在堆上。然后,可以通过指针来访问和操作这些大对象。

以下是使用C++的示例代码,演示如何在堆上分配和使用大对象:

#include 
class LargeObject {
public:
    LargeObject() {
        std::cout << "Constructor called" << std::endl;
    }
    
    ~LargeObject() {
        std::cout << "Destructor called" << std::endl;
    }
    
    // Other member functions and data members...
};
int main() {
    LargeObject* obj = new LargeObject(); // Allocate memory on the heap
    
    // Access and manipulate the large object using the pointer
    // ...
    
    delete obj; // Free the memory allocated on the heap
    
    return 0;
}

在上面的代码中,我们使用了new运算符来在堆上分配LargeObject类的对象。然后,可以使用指针obj来访问和操作这个大对象。最后,通过delete运算符释放在堆上分配的内存。

通过将大对象分配在堆上,可以避免堆栈溢出的问题,并且可以更有效地管理内存。

0
0 Comments

C和C++如何在堆栈上存储大对象?

在这个问题中,主要的原因是讨论了堆栈和堆之间的区别。堆栈和堆是两种不同的内存分配方式,它们在存储和使用大对象时有不同的表现。

解决该问题的方法是通过了解堆栈和堆的工作方式和限制,以及操作系统和编译器的特定限制。以下是解决问题的主要内容:

1. 堆栈和堆的区别:堆栈分配只需要偏移指针,并且可能在堆栈增长足够大时分配新的内存页。堆必须通过其数据结构搜索合适的内存块,并可能分配新的内存页。

2. 堆栈的作用域:堆栈的作用域在当前块结束时结束。堆的作用域在调用delete/free时结束。

3. 堆的碎片化:堆可能会出现碎片化,而堆栈则不会出现碎片化。

4. 内存分配时间:在Linux下,无论堆栈还是堆都是通过虚拟内存管理的。在分配时间方面,即使是在堆中搜索碎片化的内存,也无法与映射新的内存页相提并论。时间上的差异是可以忽略不计的。

5. 内存碎片化:当程序长时间运行时,碎片化会导致内存占用逐渐增加,最终导致性能下降。

6. 内存交换:在使用堆栈或堆上创建和销毁大对象时,可能会导致虚拟内存系统的交换。这会对性能产生较大影响。

此外,还提到了堆栈帧的大小限制,线程栈的限制以及如何在Linux/Unix/MacOS/Darwin/BSD上更改堆栈大小的方法。

堆栈和堆在存储和使用大对象时有不同的表现和限制。了解这些差异和限制有助于开发人员做出更好的内存分配决策,并优化程序的性能。

文章来源:https://stackoverflow.com/questions/84556#88675

0