2

我们正在开发一个相对大型的 C++ 项目,我们一开始就选择使用 protobuf 作为我们的通用语来存储和传输数据。

我们遇到了第一个问题,因为 protobuf 生成的类元数据存储为静态指针,在第一次调用构造函数期间分配并且从未释放,导致程序结束内存泄漏。我们发现谷歌先生提供了一个很好的功能来做这个清理:

google::protobuf::ShutdownProtobufLibrary();

工作正常,除了没有对称调用,所以一旦完成,你就不能再使用任何东西了。您必须在可执行文件中准确地执行一次。我们做了任何懒惰的开发者都会做的事情:

struct LIBPROTOBUF_EXPORT Resource
{
    ~Resource()
    {
        google::protobuf::ShutdownProtobufLibrary();
    }
};

bool registerShutdownAtExit()
{
    static Resource cleaner;
    return true;
}

并且我们在protobuf生成的cc文件中添加了一个:

static bool protobufResource = mlv::protobuf::registerShutdownAtExit();

它工作了几个月。

然后我们在我们的工具中添加了对动态可加载插件 (dll) 的支持。其中一些使用protobuf。插件的卸载工作正常,但是当其中多个插件使用 protobuf 时,我们在卸载最后一个插件时发生了一个不错的小崩溃。原因:最后一个卸载会破坏cleaner实例,它google::protobuf::ShutdownProtobufLibrary()自己试图破坏,它自己试图破坏卸载类型的元数据......崩溃。

长话短说:在关闭我们的工具时,我们是否注定要发生大量“正常”内存泄漏或崩溃。有没有人遇到过同样的问题并找到了更好的解决方案?我的诊断不好吗?

4

1 回答 1

1

就像 johnathon 在他的评论中建议的那样,使用引用计数方案,或者使用atexit. 这样的例程是独立的,但这可能适用于您的情况。

相关文件:

编辑:你是对的,它基本上是一样的。没想到这一点。

另一个建议:对所有使用 protobuf 的插件使用全局资源单例。这个有一个全局析构函数,仅在插件第一次使用 protobuf 库时才注册。或者只是在使用时设置一个标志,然后仅在设置标志时调用 ShutdownProtobufLibrary。

于 2012-07-26T16:18:54.680 回答