Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
201 views
in Technique[技术] by (71.8m points)

c++ - Using shared_ptr in dll-interfaces

I have an abstract class in my dll.

class IBase {
  protected:
       virtual ~IBase() = 0;
  public:
       virtual void f() = 0;
};

I want to get IBase in my exe-file which loads dll. First way is to create following function

IBase * CreateInterface();

and to add the virtual function Release() in IBase.

Second way is to create another function

boost::shared_ptr<IBase> CreateInterface();

and no Release() function is needed.

Questions.

1) Is it true that the destructor and memory deallocation is called in the dll (not in exe-file) in the second case?

2) Does the second case work well if exe-file and dll was compiled with different compilers (or different settings).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

An answer to your first question: The virtual destructor in your dll is called - the information about its location is embedded in your object (in the vtable). In the case of memory deallocation it depends how disciplined the users of your IBase are. If they know they have to call Release() and consider that exception can bypass the control flow in an surprising direction, the right one will be used.

But if CreateInterface() returns shared_ptr<IBase> it can bind the right deallocation function right to this smart pointer. Your library may look like this:

Destroy(IBase* p) {
    ... // whatever is needed to delete your object in the right way    
}

boost::shared_ptr<IBase> CreateInterface() {
    IBase *p = new MyConcreteBase(...);
    ...
    return shared_ptr<IBase>(p, Destroy); // bind Destroy() to the shared_ptr
}                                         // which is called instead of a plain
                                          // delete

Thus every user of your DLL is easily prevented against resource leaks. They never have to bother about calling Release() or pay attention to exceptions bypassing surprisingly their control flow.

To answer your second question: The downside of this approach is clearly stated by the other answers: You're audience has to use the same compiler, linker, settings, libraries as you. And if they could be quite a lot this can be major drawback for your library. You have to choose: Safety vs. larger audience

But there's a possible loophole: Use shared_ptr<IBase>in your application, i.e.

{
    shared_ptr<IBase> p(CreateInterface(), DestroyFromLibrary);
    ...
    func();
    ...
}

Thus no implementation specific object is passed across the DLL boundary. Nevertheless your pointer is safely hidden behind the shared_ptr, who's calling DestroyFromLibrary at the right time even if func()'s throwing an exception or not.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...