You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

尝试删除堆分配int时触发delete_scalar.cpp错误,求问题定位与修复

问题分析与修复

用户代码

#include <iostream>
class TEST
{
public:
    int* a = new int;
    TEST(int x)
        : a(&x)
    {

    }
    ~TEST()
    {
        delete a;
    }
};

int main()
{
    {
        int i = 2;
        TEST T(i);
    }
    std::cin.get();
}

用户问题

我尝试在TEST类中堆分配整数并销毁它,但在类的析构函数中调用delete a时,触发了delete_scalar.cpp中的错误,不清楚错误含义及修复方法,请问问题出在哪里?


问题根源

  • 构造函数的初始化列表把a的地址替换成了栈变量x的地址(x是构造函数的形参,存储在栈内存中),直接丢弃了类内初始化时堆分配的内存地址,导致那块堆内存无人释放,造成内存泄漏。
  • 析构函数调用delete a时,你试图释放栈内存——delete只能用于释放new在堆上分配的内存,释放栈内存属于非法操作,这就是触发delete_scalar.cpp报错的原因。

修复方案

方案1:正确使用堆内存(符合你的初始需求)

如果你想让a指向堆上的整数并初始化,有两种写法:

写法一:保留类内堆初始化,直接给堆内存赋值

#include <iostream>
class TEST
{
public:
    int* a = new int;
    TEST(int x)
    {
        *a = x; // 给堆上的整数赋值,不修改a的地址
    }
    ~TEST()
    {
        delete a; // 释放合法的堆内存
    }
};

int main()
{
    {
        int i = 2;
        TEST T(i);
    }
    std::cin.get();
}

写法二:在构造函数中直接堆分配并初始化

#include <iostream>
class TEST
{
public:
    int* a;
    TEST(int x)
        : a(new int(x)) // 直接堆分配内存并初始化x的值
    {
    }
    ~TEST()
    {
        delete a;
    }
};

int main()
{
    {
        int i = 2;
        TEST T(i);
    }
    std::cin.get();
}

方案2:指向传入的栈变量(需注意生命周期)

如果确实需要让a指向传入的变量,那么不能调用delete a,同时要去掉类内的堆分配避免内存泄漏:

#include <iostream>
class TEST
{
public:
    int* a;
    TEST(int x)
        : a(&x)
    {
    }
    ~TEST()
    {
        // 不要调用delete a,因为a指向栈内存,会由系统自动释放
    }
};

int main()
{
    {
        int i = 2;
        TEST T(i);
    }
    std::cin.get();
}

⚠️ 注意:这种写法必须保证TEST对象的生命周期不超过传入变量的生命周期,否则a会变成野指针,访问它会触发未定义行为。


内容的提问来源于stack exchange,提问作者user20295136

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:56:07