DLL, STL and CRT linking
-
This happened to me recently (yesterday and today), and was resolved thanks to the help provided in the C++ forum. Before the answers, I did some research on google about the problem and found that this is happening in other libraries (MySQL and Qt, just to mention a few). While searching I found little to no meaningful answer, so now that it's solved (thanks again to Mark Salsbery, Gleat, Nemanja Trifunovic and David Crow) I'd like to post it here to prevent others from going through the pain I suffered. Here I go. The scenario was the following. For a project, I have three DLLs, in which reside some C++ classes : the core (classes used through all the project), the data layer and the business rules, each portion with its own DLL. Then, I have a front end, written with WTL. The data layer relies on the core, and the BR layer relies on both the core and the data layer. Finally, the front end relies on the core and the BR layer. An example of one of the core classes is the following:
// SSCORE_API defined as __declspec(dllexport) or __declspec(dllimport)
class SSCORE_API Item
{
public:
// proper constructors and virtual destructor, a 'nice' classint GetId() const; void SetId(int id);
private:
int _id;
};typedef std::vector Items;
// elsewhere
class SSCORE_API ProductItem : public Item
{
public:
// proper constructors and virtual destructor, a 'nice' classCString GetBarcode() const; void SetBarcode(const CString& barcode); // many other getters and setters
private:
CString _barcode; // ATL:::CString, that is
// many other members
};typedef std::vector ProductItems;
// in the data layer
class SSDATA_API DataProduct
{
public:
...
ProductItem GetById(int id); // queries the database by id
ProductItems& GetAll(ProductItems& items); // queries all products in db
...
};// within one of my exe's WTL dialog
void ProductDlg::FillItems()
{
ProductItems products; // remember this is a std::vector
DataProduct data(...);...
data.GetAll(products);
for (ProductItems::iterator i = products.begin();
i != products.end();
++i)
{
AddToListCtrl(*i); // populates the dialog's CListCtrl
}
...
} // error thrown here!When running the dialog's
FillItems
method, at the end VC8 called an assert and throwed me the following message:Windows has triggered a breakpoint in
-
This happened to me recently (yesterday and today), and was resolved thanks to the help provided in the C++ forum. Before the answers, I did some research on google about the problem and found that this is happening in other libraries (MySQL and Qt, just to mention a few). While searching I found little to no meaningful answer, so now that it's solved (thanks again to Mark Salsbery, Gleat, Nemanja Trifunovic and David Crow) I'd like to post it here to prevent others from going through the pain I suffered. Here I go. The scenario was the following. For a project, I have three DLLs, in which reside some C++ classes : the core (classes used through all the project), the data layer and the business rules, each portion with its own DLL. Then, I have a front end, written with WTL. The data layer relies on the core, and the BR layer relies on both the core and the data layer. Finally, the front end relies on the core and the BR layer. An example of one of the core classes is the following:
// SSCORE_API defined as __declspec(dllexport) or __declspec(dllimport)
class SSCORE_API Item
{
public:
// proper constructors and virtual destructor, a 'nice' classint GetId() const; void SetId(int id);
private:
int _id;
};typedef std::vector Items;
// elsewhere
class SSCORE_API ProductItem : public Item
{
public:
// proper constructors and virtual destructor, a 'nice' classCString GetBarcode() const; void SetBarcode(const CString& barcode); // many other getters and setters
private:
CString _barcode; // ATL:::CString, that is
// many other members
};typedef std::vector ProductItems;
// in the data layer
class SSDATA_API DataProduct
{
public:
...
ProductItem GetById(int id); // queries the database by id
ProductItems& GetAll(ProductItems& items); // queries all products in db
...
};// within one of my exe's WTL dialog
void ProductDlg::FillItems()
{
ProductItems products; // remember this is a std::vector
DataProduct data(...);...
data.GetAll(products);
for (ProductItems::iterator i = products.begin();
i != products.end();
++i)
{
AddToListCtrl(*i); // populates the dialog's CListCtrl
}
...
} // error thrown here!When running the dialog's
FillItems
method, at the end VC8 called an assert and throwed me the following message:Windows has triggered a breakpoint in
Welcome to the second circle :) It's one of the uglier things in C++ IIRC fully grasped that one day when I pondered COM's interfaces being classes with virtual methods, but not a virtual destructor - sounds like a recipe for failure, especially in the case of interfaces (as the implementation will most likely hold resources that need to be freed). But no!
IUnknown::Release
includes the deletion policy and is implemented by the final class in the server - so the server does both allocation and deallocation. This allows COM to work with components using any runtime they like for memory management. I was aware that DLLs with static CRT use a different heap from DLLs with dynamic - but until this point this was an obscure fact that didn't really matter. btw. I've usedshared_ptr
to work around this in one case, returining a pointer that includes it's deletion policy. Anything that little beast can't do for me?
We are a big screwed up dysfunctional psychotic happy family - some more screwed up, others more happy, but everybody's psychotic joint venture definition of CP
My first real C# project | Linkify!|FoldWithUs! | sighist -
This happened to me recently (yesterday and today), and was resolved thanks to the help provided in the C++ forum. Before the answers, I did some research on google about the problem and found that this is happening in other libraries (MySQL and Qt, just to mention a few). While searching I found little to no meaningful answer, so now that it's solved (thanks again to Mark Salsbery, Gleat, Nemanja Trifunovic and David Crow) I'd like to post it here to prevent others from going through the pain I suffered. Here I go. The scenario was the following. For a project, I have three DLLs, in which reside some C++ classes : the core (classes used through all the project), the data layer and the business rules, each portion with its own DLL. Then, I have a front end, written with WTL. The data layer relies on the core, and the BR layer relies on both the core and the data layer. Finally, the front end relies on the core and the BR layer. An example of one of the core classes is the following:
// SSCORE_API defined as __declspec(dllexport) or __declspec(dllimport)
class SSCORE_API Item
{
public:
// proper constructors and virtual destructor, a 'nice' classint GetId() const; void SetId(int id);
private:
int _id;
};typedef std::vector Items;
// elsewhere
class SSCORE_API ProductItem : public Item
{
public:
// proper constructors and virtual destructor, a 'nice' classCString GetBarcode() const; void SetBarcode(const CString& barcode); // many other getters and setters
private:
CString _barcode; // ATL:::CString, that is
// many other members
};typedef std::vector ProductItems;
// in the data layer
class SSDATA_API DataProduct
{
public:
...
ProductItem GetById(int id); // queries the database by id
ProductItems& GetAll(ProductItems& items); // queries all products in db
...
};// within one of my exe's WTL dialog
void ProductDlg::FillItems()
{
ProductItems products; // remember this is a std::vector
DataProduct data(...);...
data.GetAll(products);
for (ProductItems::iterator i = products.begin();
i != products.end();
++i)
{
AddToListCtrl(*i); // populates the dialog's CListCtrl
}
...
} // error thrown here!When running the dialog's
FillItems
method, at the end VC8 called an assert and throwed me the following message:Windows has triggered a breakpoint in
Hi, If you read documentation about dll's you will find that it says in many places that memory allocated in a dll shouldn't be freed in the main exe (or in another dll) and viceversa, because, as you discovered, each library can be using a different heap or memory manager. Best regards, Mauro.
-
This happened to me recently (yesterday and today), and was resolved thanks to the help provided in the C++ forum. Before the answers, I did some research on google about the problem and found that this is happening in other libraries (MySQL and Qt, just to mention a few). While searching I found little to no meaningful answer, so now that it's solved (thanks again to Mark Salsbery, Gleat, Nemanja Trifunovic and David Crow) I'd like to post it here to prevent others from going through the pain I suffered. Here I go. The scenario was the following. For a project, I have three DLLs, in which reside some C++ classes : the core (classes used through all the project), the data layer and the business rules, each portion with its own DLL. Then, I have a front end, written with WTL. The data layer relies on the core, and the BR layer relies on both the core and the data layer. Finally, the front end relies on the core and the BR layer. An example of one of the core classes is the following:
// SSCORE_API defined as __declspec(dllexport) or __declspec(dllimport)
class SSCORE_API Item
{
public:
// proper constructors and virtual destructor, a 'nice' classint GetId() const; void SetId(int id);
private:
int _id;
};typedef std::vector Items;
// elsewhere
class SSCORE_API ProductItem : public Item
{
public:
// proper constructors and virtual destructor, a 'nice' classCString GetBarcode() const; void SetBarcode(const CString& barcode); // many other getters and setters
private:
CString _barcode; // ATL:::CString, that is
// many other members
};typedef std::vector ProductItems;
// in the data layer
class SSDATA_API DataProduct
{
public:
...
ProductItem GetById(int id); // queries the database by id
ProductItems& GetAll(ProductItems& items); // queries all products in db
...
};// within one of my exe's WTL dialog
void ProductDlg::FillItems()
{
ProductItems products; // remember this is a std::vector
DataProduct data(...);...
data.GetAll(products);
for (ProductItems::iterator i = products.begin();
i != products.end();
++i)
{
AddToListCtrl(*i); // populates the dialog's CListCtrl
}
...
} // error thrown here!When running the dialog's
FillItems
method, at the end VC8 called an assert and throwed me the following message:Windows has triggered a breakpoint in
Ugly, ain't it :) ? I was planning to write an article on it, but there was always something "more urgent" to do. What we did in the past was dynamically linking CRT in all the modules, and then it just works fine, because they share the same CRT. When deploying, we would just put the crt and std cpp dlls in the same folder, and it would work like a charm. Unfortunately, with VC++ 2005 and its manifests, it is not that simple any more. BTW, on Unix system this problem is rarely an issue - libraries are almost always linked dynamically there.
-
Welcome to the second circle :) It's one of the uglier things in C++ IIRC fully grasped that one day when I pondered COM's interfaces being classes with virtual methods, but not a virtual destructor - sounds like a recipe for failure, especially in the case of interfaces (as the implementation will most likely hold resources that need to be freed). But no!
IUnknown::Release
includes the deletion policy and is implemented by the final class in the server - so the server does both allocation and deallocation. This allows COM to work with components using any runtime they like for memory management. I was aware that DLLs with static CRT use a different heap from DLLs with dynamic - but until this point this was an obscure fact that didn't really matter. btw. I've usedshared_ptr
to work around this in one case, returining a pointer that includes it's deletion policy. Anything that little beast can't do for me?
We are a big screwed up dysfunctional psychotic happy family - some more screwed up, others more happy, but everybody's psychotic joint venture definition of CP
My first real C# project | Linkify!|FoldWithUs! | sighistGreat tip on shared_ptr with custom deletion policy! I've come across an issue similar to this one, so here goes: After a large refactoring on a multi platform (CE and XP) C++ project, the CE release version was giving an access violation when entering a certain dialog. Both the debug and release XP versions were running fine and the CE debug was unusable because it was overstepping the 32MB memory limit. Several runs later, it looked like the AV was thrown in the DB layer, on inserting a value into a std::map. Always the same place, on the second insert. The main exe passed some interface pointers to a UI dll; the dll created a map and it called through the interfaces into the exe to fill the map. Both the dll and exe were linked with the dynamic CRT. Seemed to be some sort of memory corruption, so I tried to leverage the debug heap on the XP version to catch it, thinking that it manifested itself only on CE and existed in all versions, but didn't find anything. Then I tried inserting into the map in several places to see if I could trigger the bug earlier. An AV was being thrown only when you tried to insert while in the DB layer, and it worked everywhere else! Long story short, the eVC++ 4.0 std::map implementation used a static variable to keep track of the internal tree representation. When crossing the dll to exe threshold, the static would have different values and the insert would end up dereferencing a NULL pointer. Solved it by moving the entire resource management to the exe and passing the dll a higher level interface. keywords: std::map, Embedded Visual C++, Windows CE 4.2, Access violation. P.S: sorry for the double post. :)
-
This happened to me recently (yesterday and today), and was resolved thanks to the help provided in the C++ forum. Before the answers, I did some research on google about the problem and found that this is happening in other libraries (MySQL and Qt, just to mention a few). While searching I found little to no meaningful answer, so now that it's solved (thanks again to Mark Salsbery, Gleat, Nemanja Trifunovic and David Crow) I'd like to post it here to prevent others from going through the pain I suffered. Here I go. The scenario was the following. For a project, I have three DLLs, in which reside some C++ classes : the core (classes used through all the project), the data layer and the business rules, each portion with its own DLL. Then, I have a front end, written with WTL. The data layer relies on the core, and the BR layer relies on both the core and the data layer. Finally, the front end relies on the core and the BR layer. An example of one of the core classes is the following:
// SSCORE_API defined as __declspec(dllexport) or __declspec(dllimport)
class SSCORE_API Item
{
public:
// proper constructors and virtual destructor, a 'nice' classint GetId() const; void SetId(int id);
private:
int _id;
};typedef std::vector Items;
// elsewhere
class SSCORE_API ProductItem : public Item
{
public:
// proper constructors and virtual destructor, a 'nice' classCString GetBarcode() const; void SetBarcode(const CString& barcode); // many other getters and setters
private:
CString _barcode; // ATL:::CString, that is
// many other members
};typedef std::vector ProductItems;
// in the data layer
class SSDATA_API DataProduct
{
public:
...
ProductItem GetById(int id); // queries the database by id
ProductItems& GetAll(ProductItems& items); // queries all products in db
...
};// within one of my exe's WTL dialog
void ProductDlg::FillItems()
{
ProductItems products; // remember this is a std::vector
DataProduct data(...);...
data.GetAll(products);
for (ProductItems::iterator i = products.begin();
i != products.end();
++i)
{
AddToListCtrl(*i); // populates the dialog's CListCtrl
}
...
} // error thrown here!When running the dialog's
FillItems
method, at the end VC8 called an assert and throwed me the following message:Windows has triggered a breakpoint in
You really shouldn't ever allocate memory with the CRT's
malloc
/new
in one module and free it in another. It happens to work now if all modules are linked with the same version of the CRT DLLs, but I remember a blog post from the VC team saying even that might not work in the future.--Mike-- Visual C++ MVP :cool: LINKS~! PimpFish | CP SearchBar v3.0 | C++ Forum FAQ "That's what's great about doing user interface work. No matter what you do, people will say that what you did was idiotic." -- Raymond Chen
-
Welcome to the second circle :) It's one of the uglier things in C++ IIRC fully grasped that one day when I pondered COM's interfaces being classes with virtual methods, but not a virtual destructor - sounds like a recipe for failure, especially in the case of interfaces (as the implementation will most likely hold resources that need to be freed). But no!
IUnknown::Release
includes the deletion policy and is implemented by the final class in the server - so the server does both allocation and deallocation. This allows COM to work with components using any runtime they like for memory management. I was aware that DLLs with static CRT use a different heap from DLLs with dynamic - but until this point this was an obscure fact that didn't really matter. btw. I've usedshared_ptr
to work around this in one case, returining a pointer that includes it's deletion policy. Anything that little beast can't do for me?
We are a big screwed up dysfunctional psychotic happy family - some more screwed up, others more happy, but everybody's psychotic joint venture definition of CP
My first real C# project | Linkify!|FoldWithUs! | sighistpeterchen wrote:
It's one of the uglier things in C++
Yep, I just learned that ;P
peterchen wrote:
IIRC fully grasped that one day when I pondered COM's interfaces being classes with virtual methods, but not a virtual destructor - sounds like a recipe for failure, especially in the case of interfaces (as the implementation will most likely hold resources that need to be freed).
AFAIK that's why Microsoft added an extension to the
struct
keyword, in order to avoid what you mentioned: you don't need virtual destructors when deriving from it. Indeed, that's the reason why MS also added another keyword,interface
and recommended to use it instead ofclass
(which by the way,interface
it's only a#define interface struct
).peterchen wrote:
btw. I've used shared_ptr to work around this in one case, returining a pointer that includes it's deletion policy. Anything that little beast can't do for me?
Hehe, how was it? Oh yes, "peace, love and smart pointers". :)
Hope is the negation of reality - Raistlin Majere
-
Hi, If you read documentation about dll's you will find that it says in many places that memory allocated in a dll shouldn't be freed in the main exe (or in another dll) and viceversa, because, as you discovered, each library can be using a different heap or memory manager. Best regards, Mauro.
Yep. After this thing happened I re-read many of my dust-covered C++ books, and I found that thing indeed. However, I wasn't aware that both
ATL::CString
andstd::vector
did such thing --although I should have, perhaps.
Hope is the negation of reality - Raistlin Majere
-
Ugly, ain't it :) ? I was planning to write an article on it, but there was always something "more urgent" to do. What we did in the past was dynamically linking CRT in all the modules, and then it just works fine, because they share the same CRT. When deploying, we would just put the crt and std cpp dlls in the same folder, and it would work like a charm. Unfortunately, with VC++ 2005 and its manifests, it is not that simple any more. BTW, on Unix system this problem is rarely an issue - libraries are almost always linked dynamically there.
'Ugly''s meaning is not enough to describe it. ;P. After this I thought about it too, but I guess that with this post it will be enough for further developers who run into the same kind of problem (it has been already indexed by Google :cool:)
Hope is the negation of reality - Raistlin Majere
-
You really shouldn't ever allocate memory with the CRT's
malloc
/new
in one module and free it in another. It happens to work now if all modules are linked with the same version of the CRT DLLs, but I remember a blog post from the VC team saying even that might not work in the future.--Mike-- Visual C++ MVP :cool: LINKS~! PimpFish | CP SearchBar v3.0 | C++ Forum FAQ "That's what's great about doing user interface work. No matter what you do, people will say that what you did was idiotic." -- Raymond Chen
What a mess. I hoped that an ABI for C++ would solve all this things, but I guess that we'll have to wait for the next version of the standard (perhaps in 2019?).
Hope is the negation of reality - Raistlin Majere
-
Ugly, ain't it :) ? I was planning to write an article on it, but there was always something "more urgent" to do. What we did in the past was dynamically linking CRT in all the modules, and then it just works fine, because they share the same CRT. When deploying, we would just put the crt and std cpp dlls in the same folder, and it would work like a charm. Unfortunately, with VC++ 2005 and its manifests, it is not that simple any more. BTW, on Unix system this problem is rarely an issue - libraries are almost always linked dynamically there.
Nemanja Trifunovic wrote:
Unfortunately, with VC++ 2005 and its manifests, it is not that simple any more.
It's almost that simple - you just need to dump the redistributable manifest file in the same directory as your exe along with the dlls. That's what I've done with a VS2005 built program to get it to run on XP, anyway.
-
This happened to me recently (yesterday and today), and was resolved thanks to the help provided in the C++ forum. Before the answers, I did some research on google about the problem and found that this is happening in other libraries (MySQL and Qt, just to mention a few). While searching I found little to no meaningful answer, so now that it's solved (thanks again to Mark Salsbery, Gleat, Nemanja Trifunovic and David Crow) I'd like to post it here to prevent others from going through the pain I suffered. Here I go. The scenario was the following. For a project, I have three DLLs, in which reside some C++ classes : the core (classes used through all the project), the data layer and the business rules, each portion with its own DLL. Then, I have a front end, written with WTL. The data layer relies on the core, and the BR layer relies on both the core and the data layer. Finally, the front end relies on the core and the BR layer. An example of one of the core classes is the following:
// SSCORE_API defined as __declspec(dllexport) or __declspec(dllimport)
class SSCORE_API Item
{
public:
// proper constructors and virtual destructor, a 'nice' classint GetId() const; void SetId(int id);
private:
int _id;
};typedef std::vector Items;
// elsewhere
class SSCORE_API ProductItem : public Item
{
public:
// proper constructors and virtual destructor, a 'nice' classCString GetBarcode() const; void SetBarcode(const CString& barcode); // many other getters and setters
private:
CString _barcode; // ATL:::CString, that is
// many other members
};typedef std::vector ProductItems;
// in the data layer
class SSDATA_API DataProduct
{
public:
...
ProductItem GetById(int id); // queries the database by id
ProductItems& GetAll(ProductItems& items); // queries all products in db
...
};// within one of my exe's WTL dialog
void ProductDlg::FillItems()
{
ProductItems products; // remember this is a std::vector
DataProduct data(...);...
data.GetAll(products);
for (ProductItems::iterator i = products.begin();
i != products.end();
++i)
{
AddToListCtrl(*i); // populates the dialog's CListCtrl
}
...
} // error thrown here!When running the dialog's
FillItems
method, at the end VC8 called an assert and throwed me the following message:Windows has triggered a breakpoint in
Heh - it's something that we all go through eventually...I first encountered this issue about 7 or 8 years ago, so now I use a DLL version of the CRT for everything.
-
What a mess. I hoped that an ABI for C++ would solve all this things, but I guess that we'll have to wait for the next version of the standard (perhaps in 2019?).
Hope is the negation of reality - Raistlin Majere
Fernando A. Gomez F. wrote:
ABI for C++
You've got to be kidding! That would require actual leadership from folks like Bjarne, et al, and for them to ride herd on all the shitty vendor implementations so that they actually implement the damn language. Sadly you've got a better shot of getting a ride on the next lunar lander than seeing this occur, ever. :(
¡El diablo está en mis pantalones! ¡Mire, mire! Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)! SELECT * FROM User WHERE Clue > 0 0 rows returned Save an Orange - Use the VCF! VCF Blog
-
What a mess. I hoped that an ABI for C++ would solve all this things, but I guess that we'll have to wait for the next version of the standard (perhaps in 2019?).
Hope is the negation of reality - Raistlin Majere
Yeah, they're running out of time to get "C++0x" done. :rolleyes:
--Mike-- Visual C++ MVP :cool: LINKS~! CP SearchBar v3.0 | C++ Forum FAQ Dunder-Mifflin, this is Pam.