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

C++动态内存程序问题:多边形类代码存在内存泄漏求助

Polygon类内存泄漏问题排查与解决方案

问题描述

我正在编写一个为Polygon类添加点的C++程序,代码如下。程序出现内存泄漏问题,完全无从下手,恳请帮助!
UPDATE: 是否存在memcpy的替代方案?

原始代码

#include <iostream>
#include <cstring>
#include <cstdint>

struct Coordinate {
    int x, y;

    Coordinate () : x(), y() {}
    Coordinate (int _x, int _y) : x(_x), y(_y) {}
};

class Polygon {
    int points;
    Coordinate** coordinates;

public:

    Polygon (int _points) {
        points = _points;
        coordinates = new Coordinate*[points+1];
    }

    ~Polygon () {

        for (int i = 0; i <=points; i++){
            delete coordinates[i];
        }
        delete [] coordinates;

    }

    void putPoint (Coordinate ** pts) {
        for (int i = 0; i < points; i++) {
            memcpy(&coordinates[i], &pts[i%points], sizeof(coordinates[i]));
        }
    }

};

int main () {

    Coordinate q1 = {0,0};
    Coordinate q2 = {0,2};
    Coordinate q3 = {2,2};
    Coordinate q4 = {2,0};


    Coordinate* quadPts[4] = {&q1, &q2, &q3, &q4};
    Polygon * quad = new Polygon(4);

    quad->putPoint(quadPts);
}

错误信息

20066ERROR: LeakSanitizer: detected memory leaks
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7fd18ba55947 in operator new(unsigned long) (/lib/x86_64-linux-gnu/libasan.so.5+0x10f947)
Indirect leak of 32 byte(s) in 1 object(s) allocated from:
#0 0x7fd18ba55b47 in operator new[](unsigned long) (/lib/x86_64-linux-gnu/libasan.so.5+0x10fb47)

问题根源

  1. 未销毁Polygon对象:main函数中用new创建了Polygon实例,但未调用delete销毁它,导致Polygon的析构函数从未执行,内部的coordinates指针数组无法被释放,这是内存泄漏的直接原因。
  2. 指针管理错误:
    • coordinates是二级指针,构造函数仅分配了指针数组,但未为每个指针分配对应的Coordinate对象;putPoint中通过memcpy将栈上对象的地址复制到指针数组,析构时delete栈上对象的地址会触发未定义行为。
    • 构造函数分配了points+1个指针,但putPoint仅初始化了前points个,最后一个指针是野指针,析构时delete野指针同样会引发未定义行为。
  3. 不必要的memcpy:用memcpy复制指针完全多余,C++中直接赋值指针或对象即可。

解决方案

修复内存泄漏与指针问题

推荐简化类的内存管理,直接存储Coordinate对象数组(而非二级指针),避免复杂的指针操作:

#include <iostream>
#include <cstdint>

struct Coordinate {
    int x, y;

    Coordinate() : x(), y() {}
    Coordinate(int _x, int _y) : x(_x), y(_y) {}
};

class Polygon {
    int points;
    Coordinate* coordinates; // 一维对象数组,简化内存管理

public:
    Polygon(int _points) : points(_points) {
        coordinates = new Coordinate[points]; // 分配points个Coordinate对象
    }

    ~Polygon() {
        delete[] coordinates; // 直接释放对象数组
    }

    void putPoint(Coordinate* pts) {
        for (int i = 0; i < points; i++) {
            coordinates[i] = pts[i % points]; // 直接赋值对象,替代memcpy
        }
    }
};

int main() {
    Coordinate q1 = {0,0};
    Coordinate q2 = {0,2};
    Coordinate q3 = {2,2};
    Coordinate q4 = {2,0};

    Coordinate quadPts[4] = {q1, q2, q3, q4}; // 存储对象副本
    Polygon* quad = new Polygon(4);

    quad->putPoint(quadPts);
    delete quad; // 销毁Polygon对象,释放内部资源
}

memcpy的替代方案

完全不需要使用memcpy:

  • 如果存储对象:直接用=赋值Coordinate对象(如上述代码所示),C++会自动调用默认的拷贝构造函数完成对象复制。
  • 如果坚持使用指针:直接赋值指针即可(但需确保指针指向合法的堆内存,避免悬空指针),例如:
    coordinates[i] = pts[i % points]; // 直接复制指针值
    

额外说明

如果必须使用二级指针,需确保每个指针指向堆上分配的Coordinate对象,同时修正构造/析构逻辑:

// 构造函数修改为分配points个指针
Polygon(int _points) : points(_points) {
    coordinates = new Coordinate*[points];
}

// putPoint中为每个指针分配堆对象
void putPoint(Coordinate** pts) {
    for (int i = 0; i < points; i++) {
        coordinates[i] = new Coordinate(*pts[i % points]); // 复制栈对象到堆上
    }
}

// 析构函数循环到points(而非points+1)
~Polygon() {
    for (int i = 0; i < points; i++){
        delete coordinates[i];
    }
    delete[] coordinates;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:18:36