Link to home
Start Free TrialLog in
Avatar of Ashurbanipal
Ashurbanipal

asked on

heaps and stacks

Have dll that maintains its own internal database.  I just added a new routine to the dll, passing it some information from the exe.  When the routine returns, I get a crash because of a deallocation problem.

Here's the code that causes the problem, what's the trick to avoid the problem?

bool myclass::CreateTag(vector<string> *params) {

  if (params->size() != 5)
    return false;

  string x=*params->rbegin();
  params->pop_back();
  int valueindex;
  sscanf(x.data(),"%d",&valueindex);

  string y=*params->rbegin();
  params->pop_back();
  int calibrateindex;
  sscanf(y.data(),"%d",&calibrateindex);

  return false;
}
ASKER CERTIFIED SOLUTION
Avatar of DKostov
DKostov

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nietod
nietod

DKostov, is correct, but here is a "stock" answer I wrote for this problem.

*******************
The problem is that if the EXE and DLL use the staticly linked version of the run-time library (RTL), they each have their own seperate copies of the RTL.  These copies each have thier own seperate heaps for allocating memory with the new operator.   The problem is that each one does not "know" about the other.  So for example, if the DLL allocates memory, the memory comes from the heap in the DLL's copy of the RTL.  If a pointer to that memory is passed back to the EXE (it may be passed in a subtle way, like inside a class) and if that EXE later makes changes that require that the memory specified by the pointer be deleted, then the EXE will try to delete the memory, but will not be able to find the memory inside its heap.  This is is because the memory did not come from the heap.  Hence the problem.

The solution is to have the EXE and all the C++ DLLS that it uses link with the DLL version of the RTL.  Then the EXE and all the DLLS will share a single copy of the run-time library and will therefore share a single heap.

To set this in VC:

"Project" menu
"Settings..." menu item
in the dialog box that appears  "C/C++" tab
"Code generation" Category
in "Use run-time library:" select one of the DLL options.

(There are two DLLoptions there, one for a debug version, one for a release version.  Make sure you choose the setting that is right for the version you are creating)

Note that these settings need to be changed for EVERY version (debug. release etc) of the EXE and and DLLs that is shares memory with.
Avatar of Ashurbanipal

ASKER

I've got it working by making sure the exe doesn't delete dll items and vice versa.  Going to the Multithreaded dll option does not seem like a good idea.  The package has to tie into third party dll's.  I guess I just have to be careful.

Thanks
>> Going to the Multithreaded dll option does not
>> seem like a good idea.
Why not?  Its ussually a very good idea.  Not doing so is often a bad idea.

>> The package has to tie into third party dll's.
That won't matter.
nietod,
I agree with you, but probably the case is very-very special.
I think that usually Multithreaded dll opt. is good exactly when the package has to tie into third party software.
Why do you say this is a special case?  Am I missing something?

I strongly suggest the DLL RTL because this problem creeps in in many subtle ways, for example, like passing STL string classes back and forth.  Also there are other problems it solves.  For example it prevents you from having two copies of all the static "settings" in the RTL, like the new handler, the local, etc.
I'm confused.  Earlier in the suggestion I got the emphasis that both the exe and the dll needed the dll rtl option.  If this is the case, then why doesn't it matter with the third party dll?
I meant "special case" because the way that Ashurbanipal solved the specific problem from my point of view is the safest, so he could use /md option without any problems then. I tought that he had something else in mind than
only to be more careful. BTW to be careful is always a good idea :), but I
think if he wasn't sove the problem in this way the playing with the compiler options won't help for 100% of the cases for the third parties.

In my case it was an absurd to redesign the dll, but I had a chance that this is an in-house dll, so the playing with the compiler helped.
You don't have to worry about 3rd party DLLs if you use the DLL RTL.  First of all, most of these DLLs won't be C++ based or if they are C++ based, won't accept/return objects that have pointers to dynamcially allocated memory (if they have pointers, they will not be deleted except by the module that created them).  So for all of these cases, you are safe with OR without the DLL RTL and the 3rd part DLLs are safe with or without the DLL RTL.  So these cases don't matter.

The only other case is a C++ based DLL that accepts/receives objects that have pointers to dynamcally allocated memory and that expect the other modules to manipulate these pointers.  For this case you must have the DLL RTL and the 3rd party DLL must have the DLL RTL.  Now this 3rd part DLL must have been compiled to use the DLL RTL, otherwise it would never have gotten out of beta testing.  So it already uses it.  You just need to make sure you use it.  

So there is no harm in using the DLL RTL (small penalty in speed and size, and you have to ship the DLL with your app) and it eliminates potential problems.

I tried to go with Debug Multithreaded DLL for the run-time library, changing the setting for everything in the project.  The linker generated the following errors.  What library do I need to include to get rid of them, and why did they show up?  All the files built with no errors.  The dll linked with no errors.  These popped up on the executable.

nafxcwd.lib(appcore.obj) : error LNK2001: unresolved external symbol ___argv
nafxcwd.lib(appcore.obj) : error LNK2001: unresolved external symbol ___argc
nafxcwd.lib(dcprev.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(oledlgs1.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(olelink.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(dcmeta.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(timecore.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(apphelp.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(viewedit.obj) : error LNK2001: unresolved external symbol __mbctype
nafxcwd.lib(filelist.obj) : error LNK2001: unresolved external symbol __mbctype
Its sounds like it is trying to create a console application (one with a main(), like a standard C++ application).  But are wyou trying to write a windows GUI app (one with a WinMain())?  if so there is a command-line option somehere that tells it if you are making a console or gui app.  You need to specify that in the project settings (or delete the project and recreate it with the right target type.)
It's an MDI application.  I went through looking for a project setting that refers to gui or console, but didn't see any.  Deleting the project and recreating it is not a viable option.  It's a monster and a released product.

Is it a matter of just missing one library?
You can delete the project itself, without deleting the source code.  Just copy the source code and related files, like resource files to another directory.  Then delete the project directory(s).  Then you just create a new project with the same name and copy the saved source code files (and other files) over the ones created by the VC wizzard.

That or specify the right command line settings, but I can never find those, so I just delete and start over.
Actually, that might not be the cause.  It would probably complain about a missing main() to.  

Are you including any 3rd party include files or linking to a 3rd party library?
I will be linking to 3rd party libraries, but the current settings only involve this exe and the dll associated with it.

I started getting heap errors when the application closed.  Since the recommendation was that Multithreaded DLL RTL would cure this I am trying to implement it.  
I will be linking to 3rd party libraries, but the current settings only involve this exe and the dll associated with it.

I started getting heap errors when the application closed.  Since the recommendation was that Multithreaded DLL RTL would cure this I am trying to implement it.