简体   繁体   中英

Protobuf with C++ plugins

We're working on a relatively large-scale C++ project where we chose at the very beginning to use protobuf as our Lingua Franca for stored and transmitted data.

We had our first problem because of end-of-program memory leaks due to the protobuf generated classes metadata that are stored as static pointer, allocated during the first call to the constructor and never deallocated. We found a nice function provide by Mr. Google to do this clean-up:

google::protobuf::ShutdownProtobufLibrary();

Works fine except there is no symmetric call, so once it's done you can no longer use anything . You have to do that exactly one time in your executable. We did what any lazy developper would have done:

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

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

And we added in the protobuf generation of cc files a:

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

It worked fine for several months.

Then we added the support for dynamically loadable plugins (dlls) in our tool. Some of them using protobuf. Unloading of the plugins worked fine, but when more than one of them used protobuf, we had a nice little crash when unloading the last one. The reason: the last to unload would destroy the cleaner instance, itself trying to google::protobuf::ShutdownProtobufLibrary() , itself trying to destroy metadata of unloaded types... CRASH.

Long story short: are we condemned to either have lots of "normal" memory leaks or a crash when closing our tool. Does anyone have experienced the same problem and found a better solution? Is my diagnosis bad?

Like johnathon suggested in his comment, use a reference counting scheme, or register your destruction routine with atexit . Such a routine is free-standing, but that could work fine for your case.

Relevant documentation:

Edit: You're right, it's basically the same thing. Didn't think this through.

Another suggestion: Use a global resource singleton for all protobuf-using plugins. This one has a global destructor, which is only registered when a plugin first uses the protobuf library. Or just set a flag whenver it's used, then call ShutdownProtobufLibrary only if the flag is set.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM