Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

NDEBUG vs _DEBUG

Posted on 2004-11-12
17
Medium Priority
?
1,585 Views
Last Modified: 2013-12-14
Hi,

I have a problem wiht NDEBUG and _DEBUG settings from VC6. Usualy i'm delivering my DLLs compiled with NDEBUG, but the problem appears when the clients are using this dlls in their applications compiled with _DEBUG. The problem is that the application is crashing if one std object created in my DLL (NDEBUG) is distroyed in the client application (_DEBUG).

Workarounds i know for now are:
1)Always pasing objects from my dll by using referinces and never by value or smart pointers
2)delevering to the client a dll compiled with _DEBUG
3)asking the client to compile his app with NDEBUG

But i'm looking for understanding what is happening and trying to find a better solution. It's very confusing for me that a macro that was design only to enable and disable Assert functions is actually making the application to crash. Is anybody able to tell me more about this subject?

Ty
0
Comment
Question by:calisov
16 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 12564605
>>It's very confusing for me that a macro that was design only to enable and disable Assert functions is actually making the application to crash.

That macro does much more then that.
When you compile your code in debug, you're also using a different set of libraries.

For VC++, according to MS, you're not allowed to distribute the DEBUG compile version of your executable.

I recommend that you add logging features to your code, so you can better determine what's going on.
You can make it so that logging gets turned off and on, depending on a registry or INI setting.


It's hard to give you detailed advise, without knowing more about the object that is causing problems.

Can you post the class and/or implementation for this object?
0
 

Author Comment

by:calisov
ID: 12565094
There is no specific object...any object from std library(vector,string,list etc) is causing this.
Here is a short example:
dll compiled with NDEBUG:
hpp:
#ifdef      MY_EXPORTS
#define            MY_API __declspec(dllexport)
#else
#define            MY_API __declspec(dllimport)
//##########################################################################
#include <vector>
//##########################################################################
class MY_API tNdebug
{
public:
//##########################################################################
      //! Constructor
      tNdebug();
      const std::vector <double> GetVector() const;
private:
};
cpp:
#include "tNdebug.h"
//##########################################################################
tNdebug::tNdebug()
{
}
//##########################################################################
const std::vector <double> tNdebug::GetGigi() const
{
      std::vector <double>  rtrn;
      rtrn.push_back(1.0);
      rtrn.push_back(2.0);
      return rtrn;
}
client application compiled with _DEBUG:
#include "stdafx.h"
#include "tNdebug.h"
//##########################################################################
int main(int argc, char* argv[])
{
      tNdebug a;
      {
            std::vector <double> b=a.GetVector();
      }//here when the vector destructor is called i get in VC the crash
      return 0;
}



0
 

Author Comment

by:calisov
ID: 12565121
oops
Sorry for that "const std::vector <double> tNdebug::GetGigi() const" from cpp :)

It's const std::vector <double> tNdebug::GetVector() const :)...any way this is the example
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 14

Expert Comment

by:wayside
ID: 12565167
In general is it a good idea to have the module that created the object also be responsible for deleting it.

So I think the best solution is to add functions to your dll for the client to call to delete your objects, rather than having them use delete .

I could think of a couple of reasons why your scenario crashes:

1) The debug versions of new and delete allocate memory differently - the debug version of new allocates extra memory before and after the object and fills them will special values, the debug version of delete checks these guard bytes to make sure the values haven't changed. It's a mechanism to help detect overwrites and other memory corruptions.

If an object gets created with non-debug new (and doesn't have this extra space allocated with it) and then gets destroyed by the debug delete (which assumes this extra space has been allocated),  the bookkeeping gets messed up.

2) Since the debug and non-debug version are in different libraries, all of the memory allocation bookkeeping is done in two places. The debug delete is trying to free a chunk of memory it knows nothing about, which leads to a crash. It's equivalent to passing in a random value to delete.
0
 

Author Comment

by:calisov
ID: 12565718
Ok,...here are some updates....

Once i built both projects from the upper example (my dll and client app) with the same seting for "Use run-time library" ....the seting is MultiThreadedDLL...was the only one that worked .....i did not get the crash even if the dll had the NDEBUG and the client app had _DEBUG....but...as soon as i switched from vector to string i got the error back.
0
 
LVL 30

Expert Comment

by:Axter
ID: 12565740
>>There is no specific object...any object from std library(vector,string,list etc) is causing this.

Make sure your client is using the same STL library as you.
You should both  be using standard headers that are part of the C++ standard.
#include <vector>
#include <string>
#include <iostream>

If you're using the above headers, and your client is using the following none standard headers, that could be causing the problem:
#include <vector.h>
#include <string.h>
#include <iostream.h>
0
 
LVL 30

Expert Comment

by:Axter
ID: 12565765
>>Use run-time library" ....the seting is MultiThreadedDLL

If both projects are not using the same run-time library, then that will cause a crash because they're not using the same allocator/heap.

You need both to use the same run-time library.
0
 

Author Comment

by:calisov
ID: 12566534
Yes now i know that both projects must use the same run-time library...but as i told you this is ok ONLY for vector....as soon as i switched to string the error is back.


The upper example was compiled and test on my computer so, yes, for sure is the same STL.
Ok....i made more tests and here is a short report.The tests are made with the upper example as model and both projects using "MultiThreadedDLL"

For std::vector:
 - working fine even if the dll has NDEBUG and application has _DEBUG

For std::string:
- if the dll has NDEBUG and the application has _DEBUG then i get the crash
- If i keep this setings but insetad of returning by value: "const std::string GetString()" i'm using returning by ref. :
"const std::string& GetString()"  with keeping the app caling line:
int main(int argc, char* argv[])
{
     tNdebug a;
     {
          std::string b=a.GetString();
     }
     return 0;
}
then the crash is gone and evrything is working fine

For std::set or std::map
- if the dll has NDEBUG and the application has _DEBUG then i get the crash
- If i keep this setings but insetad of returning by value: "const std::set<int>  GetSet()" i'm using returning by ref. :
"const std::set<int>& GetSet()" with keeping the app caling line:
nt main(int argc, char* argv[])
{
     tNdebug a;
     {
          std::set <int> b=a.GetSet();
     }
     return 0;
}
 then i get the crash
- MORE THEN THIS..... even compiling both applications with NDEBUG and returnign by ref...i still get the crash.....

Ok....now i can realy say that THIS IS A BIG MESS FROM M.S.

PS: in .Net evrything is working fine even if i have the dll compiled with "MultiThreadedDLL" and the client app with
"MultiThreaded Debug DLL"....which is a normal behaivior.....but unfortunally for now is not an option to switch to .NET
0
 
LVL 30

Expert Comment

by:Axter
ID: 12566876
For most off the above issues, the problem is that with the STL library you need to be using the same run-time library if any deallocation occurs accross both DLL/EXE.
The debug version uses a different runtime library then the release version.

You can minimize the damage by using methods that will insure deallocation occurs in your DLL, instead of the calling application.
0
 
LVL 30

Expert Comment

by:Axter
ID: 12566913
>>Ok....now i can realy say that THIS IS A BIG MESS FROM M.S.

This is not a problem with M.S.
The debug version of the library has a lot of code that you would not want in a release version of the library.
That means to keep the release version efficient, they have to make the release version incompatible with the debug version.
0
 

Author Comment

by:calisov
ID: 12567035
i was talking about the set and map.....even with both projects using release version there is still a crash.....and this why i say that this is a MESS

And also i was not speaking about delevering to the client the debug version or about having debug code in my release......i was talking about:
1) Delivering to the client a release version of DLLs
2) Let the client debuging his application while he is using my dlls

But ofcourse...this is just a point of view.....

And it looks like the guys from MS are thinking like me also since this is no more happening in .NET.....or maybe what i'm thinking that it is a fix is actually a bug...should i report it :)?
0
 
LVL 30

Expert Comment

by:Axter
ID: 12567091
>>i was talking about the set and map.....even with both projects using release version there is still a crash.....and this why i say that this is a MESS

I would consider that a bug.
Can you post the code for GetSet function?
0
 
LVL 30

Expert Comment

by:Axter
ID: 12567104
>>or maybe what i'm thinking that it is a fix is actually a bug...should i report it :)?

If you're referring to the std::set and std::map issue, I would report it if you're sure that's what's causing the problem.
0
 
LVL 86

Expert Comment

by:jkr
ID: 12567184
>>But i'm looking for understanding what is happening and trying to find a better solution

What is happening is the following: Release and Debug modules use different heaps. Do, if you allocate aon object on the Release heap and try to free it in a Debug module, that will crash. One of the easiest workarounds is to have the objecs free themselves (since they know the approprate heap) by adding a method to do that implicitly rather explicitly:

struct IExportable {

    virtual void Release () { delete this;}
};

Have the exported classes inherit from the above one and the problems should vanish.
0
 
LVL 30

Accepted Solution

by:
Axter earned 500 total points
ID: 12567222
>>Have the exported classes inherit from the above one and the problems should vanish.

You also have to worry about returning std::string by value, which causes the reference counter to be used.

I believe passing an std::string by value will also cause the same problem.
0
 

Author Comment

by:calisov
ID: 12582335
>>What is happening is the following: Release and Debug modules use different heaps. Do, if you allocate aon object >>on the Release heap and try to free it in a Debug module, that will crash. One of the easiest workarounds is to have >>the objecs free themselves (since they know the approprate heap) by adding a method to do that implicitly rather >>explicitly:
>>
>>struct IExportable {
>>
>>    virtual void Release () { delete this;}
>>};

Does not make any sence...the object is not created with new and it is not destroyed with delete.....it is created natural
sdt::string myObject="any text";

and the destructor is automatically called by compiler when the object is geting out of its scope....
What you are sayng is "to have the objecs free themselves"....but they should  already do this since the compiler is calling their own destructor...virtual void Release () { delete this;} shoul be exactly what the implicit destructor is doing..... and this is my big question...if the object is not created with new ....since the object knows how to distroy itself.....why i'm geting problems?
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.
Suggested Courses

581 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question