Question

Is it valid to develop a DLL in C++ that returns boost shared pointers and uses them as parameters?

So, is it ok to export functions like this?

1.) boost::shared_ptr<Connection> startConnection();
2.) void sendToConnection(boost::shared_ptr<Connection> conn, byte* data, int len);

In special: Does the reference count work across DLL boundaries or would the requirement be that exe and dll use the same runtime?

The intention is to overcome the problems with object ownership. So the object gets deleted when both dll and exe don't reference it any more.

Was it helpful?

Solution

According to Scott Meyers in Effective C++ (3rd Edition), shared_ptrs are safe across dll boundaries. The shared_ptr object keeps a pointer to the destructor from the dll that created it.

In his book in Item 18 he states, "An especially nice feature of tr1::shared_ptr is that it automatically uses its per-pointer deleter to eliminate another potential client error, the "cross-DLL problem." This problem crops up when an object is created using new in one dynamically linked library (DLL) but is deleted in a different DLL. On many platforms, such cross-DLL new/delete pairs lead to runtime errors. tr1::shared_ptr avoid the problem, because its default deleter uses delete from the same DLL where the tr1::shared_ptr is created."

Tim Lesher has an interesting gotcha to watch for, though, that he mentions here. You need to make sure that the DLL that created the shared_ptr isn't unloaded before the shared_ptr finally goes out of scope. I would say that in most cases this isn't something you have to watch for, but if you're creating dlls that will be loosely coupled then I would recommend against using a shared_ptr.

Another potential downside is making sure both sides are created with compatible versions of the boost library. Boost's shared_ptr has been stable for a long while. At least since 1.34 it's been tr1 compatible.

OTHER TIPS

In my opinion, if it's not in the standard and it's not an object/mechanism provided by your library, then it shouldn't be part of the interface to the library. You can create your own object to do the reference counting, and perhaps use boost underneath, but it shouldn't be explicitly exposed in the interface.

DLLs do not normally own resources - the resources are owned by the processes that use the DLL. You are probably better off returning a plain pointer, which you then store in a shared pointer on the calling side. But without more info it's hard to be 100% certain about this.

Something to lookout for if you expose raw pointers from a dll interface. It forces you to use the shared dll CRT, memory allocated in one CRT cannot be deallocated in a different CRT. If you use the shared dll CRT in all your modules ( dll's & exe's ) then you are fine, they all share the same heap, if you dont you will be crossing CRT's and the world will meltdown.

Aside from that issue, I agree with the accepted answer. The creation factory probably shouldn't define ownership & lifecycle management for the client code.

No it is not.

The layout of boost::shared_ptr<T> might not be the same on both sides of the DLL boundary. (Layout is influenced by compiler version, packing pragmas, and other compiler options, as well as the actual version of the Boost source code.)

Only "standard layout" (a new concept in C++11, related to the old "POD = plain old data" concept) types can safely be passed between separately-built modules.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top