首页 > 解决方案 > std::shared_ptr(s) 和内存泄漏

问题描述

我的问题是当我创建 2 个共享指针时,它总是说我在运行后有内存泄漏。

解构器或指针在执行结束时的某个时间点被调用,这意味着它们正在被销毁。

但是输出窗口仍然显示内存泄漏。

这是正常的吗?

注意:我也可以只用一个单例来解决这个问题

(头文件)

class SRNTY_API Log
{
public:
    inline static std::shared_ptr<sty::Logger>& GetEngineLogger() { return mEngineLogger; }
    inline static std::shared_ptr<sty::Logger>& GetClientLogger() { return mClientLogger; }

private:
    static std::shared_ptr<sty::Logger> mEngineLogger;
    static std::shared_ptr<sty::Logger> mClientLogger;
};

(源文件)

std::shared_ptr<sty::Logger> Log::mEngineLogger = std::make_shared<sty::Logger>();
std::shared_ptr<sty::Logger> Log::mClientLogger = std::make_shared<sty::Logger>();
下面更新

我被问到他对这个问题的评论我是如何检查内存泄漏的。我可以确认我没有使用_CRTDBG_CHECK_ALWAYS_DF标志,并且我正在调用_CrtDumpMemoryLeaks()输出泄漏量并且还断言该值应该为 0。我将展示一个代码示例。

int main(int argc, char* argv[])
 {
    // detect memory leaks
#if defined(DEBUG) | defined(_DEBUG)
    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    _CrtSetBreakAlloc(0);
    //int mlCount = _CrtDumpMemoryLeaks();
    //wprintf(L"Number of memory Leaks: %d\r\n\r\n", mlCount);
    //assert(mlCount == 0);
#endif

    // run main loop

    _CrtDumpMemoryLeaks(); // attempted calling it here and still got memory leaks as it must release the shared pointers after it returns
    return 0;
}

所以我了解到它std::shared_ptr<T>在完全返回操作系统后会释放 's。但它在运行后仍然显示错误的内存泄漏。

我尝试过的其他事情是:

Singleton我做了一个Singleton界面,我没有问题,也没有内存泄漏。但是我不反对Singleton,但我更喜欢使用 c++ std lib 的共享指针,因为毫无疑问它们比我的Singleton解决方案更好,而且编译器将针对 std lib 而不是我的代码进行优化。

我已经搜索了一个要调用的位置,CrtDumpMemoryLeaks()但是我构建代码的方式我无法在 Log 析构函数中调用它,甚至不确定它会产生正确的结果并且不会显示内存泄漏。

(不可复制的.h)

class INonCopyable
{
protected:
    INonCopyable(void) {}
    virtual ~INonCopyable(void) {}
private:
    INonCopyable(const INonCopyable& other) = delete;
    const INonCopyable& operator= (const INonCopyable& other) = delete;
};

(ingleton.h)

template<typename T>
class ISingleton : public INonCopyable
{
public:
    inline static T& GetInstance() { if (!mInstance) { mInstance = new T(); } return *mInstance; }
    inline static void DestroyInstance() { delete mInstance; mInstance = nullptr; }

private:
    inline static T* mInstance = nullptr;
};

使用Singleton更改时 Log 类的实现方式

class SRNTY_API EngineLog : public ISingleton<EngineLog>, public sty::Logger
{
};

class SRNTY_API ClientLog : public ISingleton<ClientLog>, public sty::Logger
{
};

总结:

使用时没有内存泄漏Singleton,我可以使用它吗?在 c++17 中它是线程安全的吗?如果可能的话std::share_ptr<T>,我应该何时何地调用该CrtDumpMemoryLeaks()函数?或者我应该如何实现std::share_ptr<T>'s以避免错误的内存泄漏?

希望这能解决问题:)

标签: c++pointersmemory

解决方案


我只想自己回答这个问题。

首先感谢那些评论和提供信息的人。

使用std::shared_ptr<T>时,问题是手动调用_CrtDumpMemoryLeaks()您需要做的是使用在_CRTDBG_CHECK_ALWAYS_DF运行结束时自动检查内存泄漏的标志。

我最终使用的代码是:

    // detect memory leaks
#if defined(DEBUG) | defined(_DEBUG)
    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF) | _CRTDBG_CHECK_ALWAYS_DF); // added in _CRTDBG_CHECK_ALWAYS_DF
    _CrtSetBreakAlloc(0);
#endif

希望这对将来的人有所帮助:)


推荐阅读