MS VS 6: passing boost::shared_ptr<T> to a dll function
Hi all, I am trying to pass a smart pointer (boost::shared_ptr<T>) as an argument to a function that is implemented by a dll and called by an executable, but whenever I execute the application, it goes into a loop, no matter what the type of T is. When the function is implemented in the exe or when the function is called from inside the dll it works fine. Does anybody have a clue what could be happening? BTW, I'm not implicating a bug in boost, I know that it could as well be a MS VC++ bug but I would just like to know how this comes and how I can solve it. Corno PS I've tried to post this message directly to the newsgroup but that did not work. Is that news group perhaps read only?
I don't know about MS, but in Borland a common source of DLL interface problems is not using a common (shared) memory manager. You might also check up on byte alignment.(4,8,16, or32 ?) Other possibilities arise from other argument passed, which might be structs with >different< definitions in the main and dll modules, e.g., std::ostream in multithread and non-multithread modes. Craig Hicks lognez wrote:
Hi all,
I am trying to pass a smart pointer (boost::shared_ptr<T>) as an argument to a function that is implemented by a dll and called by an executable, but whenever I execute the application, it goes into a loop, no matter what the type of T is. When the function is implemented in the exe or when the function is called from inside the dll it works fine. Does anybody have a clue what could be happening? BTW, I'm not implicating a bug in boost, I know that it could as well be a MS VC++ bug but I would just like to know how this comes and how I can solve it.
Corno
PS I've tried to post this message directly to the newsgroup but that did not work. Is that news group perhaps read only?
Info: http://www.boost.org Wiki: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl Unsubscribe: mailto:boost-users-unsubscribe@yahoogroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
From: "lognez"
Hi all,
I am trying to pass a smart pointer (boost::shared_ptr<T>) as an argument to a function that is implemented by a dll and called by an executable, but whenever I execute the application, it goes into a loop, no matter what the type of T is. When the function is implemented in the exe or when the function is called from inside the dll it works fine.
Which version of boost?
"hicks"
I don't know about MS, but in Borland a common source of DLL interface problems is not using a common (shared) memory manager.
Thanx Craig, that turned out to be the problem for VC++ as well. Corno
From:
"hicks"
wrote in message news:3D0D33EE.1050007@kgk.co.jp... I don't know about MS, but in Borland a common source of DLL interface problems is not using a common (shared) memory manager.
Thanx Craig, that turned out to be the problem for VC++ as well.
Yep, but shared_ptr is supposed to work in this case, in theory. ;-) I'll look into this. Any more information that can help me find the problem?
I don't know about MS, but in Borland a common source of DLL interface problems is not using a common (shared) memory manager.
Thanx Craig, that turned out to be the problem for VC++ as well.
Yep, but shared_ptr is supposed to work in this case, in theory. ;-) I'll look into this. Any more information that can help me find the problem?
It works if the destructor of the object being held in the shared_ptr or scoped_ptr is not implemented inline in the header file. If it *is* then destruction is called in the context of whoever is currently holding the smart pointer to it at the time - and if that is across a dll boundary from the creation site then *bang* (if you have mismatched runtime models). For example - this class would exhibit the problem (well, on VC++ at least): class Awkward { public: Awkward(){} ~Awkward(){} // because the implemention (although empty) is defined here we get a problem }; If you now hold a shared_ptr to an Awkward object that was created within a host process and pass it by shared_ptr into a sink function in a dll (ie a function that allows the shared_ptr to go out of scope when the ref count is 1, thus deleting the object), then it will try to delete it from the *host process' heap*. At least, that is my experience. The simple solution, of course, is to put the destructor implementation in the implementation (cpp) file. On VC++ (and probably others), not defining a destructor has the same effect as defining one in the header file. HTH, [)o IhIL..
/ Phil Nach Wrote: /The simple solution, of course, is to put the destructor implementation in /the implementation (cpp) file. On VC++ (and probably others), not defining a /destructor has the same effect as defining one in the header file. /HTH, That would still mean that you couldn't have any STL members (not only auto ptr but e.g., vector as well) that could undergo a reallocation outside of the host class compiled code. (It doesn't matter whether these members are public or not). This is acutally quite restrictive; you have to pretty much avoid non-const inline functions which would lead to a size change, and some of these functions may be implicit, as in operator =(). If you were really determined to not use a shared memory manager, I think it would be better to go "pimple" (pointer to implementation, as promulgated by Herb Sutter) and hide everything in the DLL compiled file. Cheerio Craig Hicks Phil Nash wrote:
I don't know about MS, but in Borland a common source of DLL interface problems is not using a common (shared) memory manager.
Thanx Craig, that turned out to be the problem for VC++ as well.
Yep, but shared_ptr is supposed to work in this case, in theory. ;-) I'll look into this. Any more information that can help me find the problem?
It works if the destructor of the object being held in the shared_ptr or scoped_ptr is not implemented inline in the header file. If it *is* then destruction is called in the context of whoever is currently holding the smart pointer to it at the time - and if that is across a dll boundary from the creation site then *bang* (if you have mismatched runtime models).
For example - this class would exhibit the problem (well, on VC++ at least):
class Awkward { public: Awkward(){} ~Awkward(){} // because the implemention (although empty) is defined here we get a problem };
If you now hold a shared_ptr to an Awkward object that was created within a host process and pass it by shared_ptr into a sink function in a dll (ie a function that allows the shared_ptr to go out of scope when the ref count is 1, thus deleting the object), then it will try to delete it from the *host process' heap*.
At least, that is my experience.
The simple solution, of course, is to put the destructor implementation in the implementation (cpp) file. On VC++ (and probably others), not defining a destructor has the same effect as defining one in the header file. HTH,
[)o IhIL..
Info: http://www.boost.org Wiki: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl Unsubscribe: mailto:boost-users-unsubscribe@yahoogroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
[Non-text portions of this message have been removed]
"Phil Nash"
I don't know about MS, but in Borland a common source of DLL interface problems is not using a common (shared) memory manager.
Thanx Craig, that turned out to be the problem for VC++ as well.
Yep, but shared_ptr is supposed to work in this case, in theory. ;-) I'll look into this. Any more information that can help me find the problem?
It works if the destructor of the object being held in the shared_ptr or scoped_ptr is not implemented inline in the header file. If it *is* then destruction is called in the context of whoever is currently holding the smart pointer to it at the time - and if that is across a dll boundary from the creation site then *bang* (if you have mismatched runtime models).
I think this only holds if the raw pointer is passed out of the DLL where it was created before the shared_ptr<> gets a chance to take ownership. The cure: don't pass raw pointers around. -Dave
/David Abrahams wrote: /I think this only holds if the raw pointer is passed out of the DLL where it /was created before the shared_ptr<> gets a chance to take ownership. The /cure: don't pass raw pointers around. / /-Dave I don't think that is correct general conclusion. The root of the problem is that template code in a header can be compiled on either side of the DLL boundary. Here is a common perfectly legal scenario: Class A { .... std::vector<int> vi; .... A(); ~A(); } Constructor and destructor are both explicit and compiled on the DLL side. Copy operator (operator =) is implicit and compiled on the application (DLL client) side. (No explcit copy constructor.) Suppose a copy of an instance of "A" is made on application side. A a1 = a0; The code in vector will make allocate for the new vector using the client side version of new[], but when that object is destructed ithe same memory will be freed with the DLL version of delete[]. If these two cases have differing memory managers, to be precise differening tables of used and free memory, this is illegal and will result in unpredicatable behaviour. Craig Hicks David Abrahams wrote:
"Phil Nash"
wrote in message news:00fc01c21621$d3e29950$700a0c0a@TimeMachine... I don't know about MS, but in Borland a common source of DLL
interface
problems is not using a common (shared) memory manager.
Thanx Craig, that turned out to be the problem for VC++ as well.
Yep, but shared_ptr is supposed to work in this case, in theory. ;-)
I'll
look into this. Any more information that can help me find the problem?
It works if the destructor of the object being held in the shared_ptr or scoped_ptr is not implemented inline in the header file. If it *is* then destruction is called in the context of whoever is currently holding the smart pointer to it at the time - and if that is across a dll boundary
from
the creation site then *bang* (if you have mismatched runtime models).
I think this only holds if the raw pointer is passed out of the DLL where it was created before the shared_ptr<> gets a chance to take ownership. The cure: don't pass raw pointers around.
-Dave
Info: http://www.boost.org Wiki: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl Unsubscribe: mailto:boost-users-unsubscribe@yahoogroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
[Non-text portions of this message have been removed]
"hicks"
/David Abrahams wrote:
/I think this only holds if the raw pointer is passed out of the DLL where
it
/was created before the shared_ptr<> gets a chance to take ownership. The /cure: don't pass raw pointers around. / /-Dave
I don't think that is correct general conclusion.
I wasn't making a general conclusion. This is about shared_ptr.
The root of the problem is that template code in a header can be compiled on either side of the DLL boundary. Here is a common perfectly legal scenario:
Class A { .... std::vector<int> vi; .... A(); ~A(); } Constructor and destructor are both explicit and compiled on the DLL side. Copy operator (operator =) is implicit and compiled on the application (DLL client) side. (No explcit copy constructor.)
Suppose a copy of an instance of "A" is made on application side. A a1 = a0; The code in vector will make allocate for the new vector using the client side version of new[], but when that object is destructed ithe same memory will be freed with the DLL version of delete[]. If these two cases have differing memory managers, to be precise differening tables of used and free memory, this is illegal and will result in unpredicatable behaviour.
Have you looked carefully at the implementation of shared_ptr? -Dave
participants (6)
-
cornoï¼ dds.nl
-
David Abrahams
-
hicks
-
lognez
-
Peter Dimov
-
Phil Nash