【问题标题】:Detected memory leaks in c++在 C++ 中检测到内存泄漏
【发布时间】:2022-01-11 08:20:44
【问题描述】:

由 grpc (grpc.pb.cc) 生成的文件中的以下声明会导致内存泄漏。 google::protobuf::ShutdownProtobufLibrary() 似乎没有释放此声明分配的内存。 你能告诉我如何释放它吗?

PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_DxpGrpc_2eproto(&descriptor_table_DxpGrpc_2eproto);

Windows、C++、gRPC-1.40.0

在Windows c++环境中创建一个控制台应用程序并执行以下代码。

#include <crtdbg.h>.
#include "google/protobuf/service.h";

int main(int argc, char** argv) {
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    google::protobuf::ShutdownProtobufLibrary();
    return 0;
}

以下泄漏将被淘汰。

Detected memory leaks!
Dumping objects -> {159}
{Normal block at 0x00E49B18, 8 bytes long.
 Data: < k > 10 6B C9 00 00 00 00 00 
Object dump complete.

在grpc.pb.cc中声明AddDescriptorsRunner时,会调用下面类的DefaultConstruct()。

(文件:third_party\protobuf\src\google\protobuf\message_lite.h)

template <typename T>.
class ExplicitlyConstructed {
 public:
  void DefaultConstruct() { new (&union_) T(); }
  template <typename... Args>
  void Construct(Args&&... args) {
    new (&union_) T(std::forward<Args>(args)...) ;
  }

  void Destruct() { get_mutable()->~T(); }

  constexpr const T& get() const { return reinterpret_cast<const T&>(union_); }
  T* get_mutable() { return reinterpret_cast<T*>(&union_); }

 private:
  // Prefer c++14 aligned_storage, but for compatibility this will do.
  union AlignedUnion {
    alignas(T) char space[sizeof(T)];
    int64 align_to_int64;
    void* align_to_ptr;
  } union_;
};

【问题讨论】:

    标签: c++ visual-studio protocol-buffers grpc grpc-c++


    【解决方案1】:

    静态或全局对象在atexit 之后的最后一件事被释放,调试器报告错误泄漏。这个行为可以用这个例子重现:

    #include <Windows.h>
    std::string str;
    int main() 
    {
        _CrtDumpMemoryLeaks();//str is not freed yet
        return 0;
    }
    

    您可以创建一个结构并将泄漏报告放在析构函数中,如下所示。请注意,在此示例中,std::string str; 用于导致泄漏报告。

    如果未定义cleanup,或者如果cleanupstd::string str; 之后定义,则报告错误泄漏。定义的顺序很重要。

    #include <iostream>
    #include <string>
    #include <Windows.h>
    
    struct cleanup_t
    { 
        ~cleanup_t() { if(IsDebuggerPresent()) _CrtDumpMemoryLeaks(); }
    } cleanup;
    
    std::string str;
    
    int main() 
    {
        return 0;
    }
    

    【讨论】:

    • 对不起,还没有解决。我错误调试。确实可以按声明的顺序发生泄漏,但我无法确定是否是这种情况。我已经按照描述定义了“清理”结构并检查了它,但泄漏仍然发生。我在以下表明正在发生泄漏的声明之前和之后进行了尝试,并且确实如此。 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_DxpGrpc_2eproto(&descriptor_table_DxpGrpc_2eproto);
    • void Destruct(){...} 中设置一个调试断点以确保new (&amp;union_)delete 平衡,为泄漏报告添加另一个断点。
    • 'void Destruct()' 永远不会被调用。以下代码中的“DestroyString(const void* s)”由“google::protobuf::ShutdownProtobufLibrary();”调用。 's'是union的地址,所以我认为发布过程会在这个上面执行。(third_party\protobuf\src\google\protobuf\generated_message_util.cc)'google::protobuf::internal::DestroyString(const void* s) { static_cast(s)->~basic_string();}'
    猜你喜欢
    • 2021-09-01
    • 2012-07-16
    • 2012-01-22
    • 2011-05-12
    • 2011-02-18
    • 1970-01-01
    • 2016-12-20
    相关资源
    最近更新 更多