处理分配的内存和堆栈内存

Handling allocated and stack memory

本文关键字:内存 堆栈 分配 处理      更新时间:2023-10-16

我提供了两种向我的集合添加元素的方法,一种是每个常量引用,一次是每个指针。

void push_back(const value_type *val) {
    element *elem = new element(val);
    //...
}
void push_back(const value_type &val) {
    push_back(&val);
}

element类将值保存为指针。

class element {
private:
    const value_type *value;
public:
    element(const value_type *value):
    value(value) {
    } 
    ~element() {
        delete value;
    }

显然,当弹出元素或删除集合时,如果将元素添加为指针,则必须释放内存。但是,当元素未手动分配并通过引用传递时,这会产生错误。

如果元素是按时间动态分配的,除了额外存储之外,还有其他选择push_back吗?

只要保持一致,并始终存储一个可以删除的指针。

void push_back(const value_type &val) {
    push_back(new value_type(val));
}

总的来说,这是一个有缺陷的设计。您可以通过不同的方式更改设计以实现所需的内容。例如,马克的回答是一种直截了当的方法

话虽如此,这是使用您的设计的可能解决方案。再一次,我不推荐它,因为它依赖于编译器如何构建堆栈的内部结构,并且不能跨编译器/平台移植。

基本上,在~element()中,您可以通过将其与当前堆栈指针进行比较来检查存储在 value 中的地址是在堆栈上还是在堆上。如果存储在 value 中的地址高于堆栈指针,则它在堆栈上,不应删除(提供堆栈在地址空间顶部的通常位置)。如果它小于堆栈指针 - 它在堆上。

说明地址关系的代码(GCC,x64 linux):

#include <iostream>
int main()
{
 int * heap_(new int(0));
 int stack_(0);
 void * rsp_(nullptr);
 asm("mov %%rsp, %0" : "=m" (rsp_));
 std::cout << "heap addresst: " << heap_ 
           << "nstack addresst: " << &stack_ 
           << "nstack pointert: " << rsp_ << std::endl;
 delete (heap_);
 return (0);
}

程序输出:

heap address    : 0xc52010
stack address   : 0x7fff528ffee4
stack pointer   : 0x7fff528ffee0

ideone.com 可以访问 GCC,但使用 x86 版本 - esp注册而不是rsp .代码必须更改(不可移植性)。