【问题标题】:Visual C++ memory leakVisual C++ 内存泄漏
【发布时间】:2018-01-03 11:40:36
【问题描述】:

我正在创建一个串行通信库,它是一个托管程序集,带有它自己的规则(我不完全理解它们,我只是在 VS 抱怨时更改代码),并且我有一个内存泄漏我想不通。

这是我得到的泄漏警告(第 11 行是 SerialComm::SerialComm() 中的 InfoContainer 构造函数):

Detected memory leaks!
Dumping objects ->
SerialComm.cpp(11) : {144} normal block at 0x011468B8, 56 bytes long.
Data: <                > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Object dump complete.

这是 lib 的 .h 文件:

#include <windows.h>
#include <stdlib.h>
#include <atlstr.h>

public class InfoContainer {
public:
    ~InfoContainer();
    HANDLE handle;
    bool connected;
    COMSTAT status;
    DWORD errors;
    DCB connection_params;
    CStringA port_name;
};

public ref class SerialComm {
public:
    InfoContainer* info=0;
    SerialComm();
    ~SerialComm();
    bool OpenConnection(String^ Portname);
    int CloseConnection();
    bool WriteData(String^ toSend);
    String^ ReadData(int bytesToRead);
};

这些是相关的 .cpp 部分:

SerialComm::SerialComm() {
    info = new (_NORMAL_BLOCK, __FILE__, __LINE__) InfoContainer();
    info->handle = 0;
}
SerialComm::~SerialComm() {
    CloseConnection();
    delete info;
}

bool SerialComm::OpenConnection(String ^ Portname) {
    info->port_name = Portname;

    //visual studio's valgrindish tool
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    _CrtDumpMemoryLeaks();


    info->handle = CreateFileA(
        info->port_name,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL

    );
    if (info->handle == INVALID_HANDLE_VALUE) {
        ATLTRACE("Error: %d", GetLastError());
        printf("Error: %d\n", GetLastError());
        return false;
    }
    //
    //rest of connection code here
    //
}

int SerialComm::CloseConnection() {
    return CloseHandle(info->handle);
}

InfoContainer::~InfoContainer() {
    delete handle;
}

我必须在主类中使用 InfoContainer 类和 InfoContainer 指针的原因是我需要存储的一些信息被认为是非托管代码,因此我不能直接在主类中拥有它。

提前致谢!

【问题讨论】:

  • 在 VS Watch Window 中写入值 = -1 的 _crtBreakAlloc 。现在将其值设置为 144。那么 VS 应该在第 144 次内存分配时中断。

标签: windows visual-studio visual-c++ c++-cli managed-c++


【解决方案1】:

问题是_CrtDumpMemoryLeaks()在所有对象被删除之前被调用。

您需要一个终结器。以下是使用 C++/CLI 编写类时的“黄金模式”:

virtual ~SerialComm()
{
    this->!SerialComm();
}

!SerialComm()
{
}

不要忘记将 virtual 添加到您的析构函数中。需要虚拟析构函数的原因应该在任何好的 C++ 教科书中都有解释。

【讨论】:

  • 我不明白我应该做什么。我做了一个终结器,并将析构函数代码移入其中,然后从析构函数中调用终结器,但我仍然遇到内存泄漏,现在尝试关闭句柄时出现 SEHException。
  • 你能告诉我你的 main() 函数吗?你在用gcnew吗?还要检查编译器选项 [Configuration Properties] - [C/C++] - [Code Generation] - [Enable C++ Exceptions] for SEHException。
  • 我实际上将它编译为托管 dll。我不能将 gcnew 用于 InfoContainer,因为它包含非托管资源。这是主要的:gist.github.com/anonymous/0b24ad9df664cbce9a24bc57548d72dc
  • 我检查了你的主要功能代码。它是用 C# 编写的。顺便说一句,我找到了内存泄漏的根本原因。请参阅上面我修改后的答案。
猜你喜欢
  • 2011-02-18
  • 1970-01-01
  • 2016-01-27
  • 2010-11-11
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 2013-05-18
相关资源
最近更新 更多