6

I have a native DLL that is a plug-in to a different application (one that I have essentially zero control of). Everything works just great until I link with an additional .lib file (links my DLL to another DLL named ABQSMABasCoreUtils.dll). This file contains some additional API from the parent application that I would like to utilize. I haven't even written any code to use any of the functions exported but just linking in this new DLL is causing problems. Specifically, I get the following error when I attempt to run the program:

The application failed to initialize properly (0xc0000025). Click on OK to terminate the application.

I believe I have read somewhere that this is typically due to a DllMain function returning FALSE. Also, the following message is written to the standard output:

ERROR: Memory allocation attempted before component initialization

I am almost 100% sure this error message is coming from the application and is not some type of Windows error.

Looking into this a little more (aka flailing around and flipping every switch I know of) I linked with /MAP turned on and found this in the resulting .map file:

 0001:000af220       ??3@YAXPEAX@Z              00000001800b0220 f   ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
 0001:000af226       ??2@YAPEAX_K@Z             00000001800b0226 f   ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
 0001:000af22c       ??_U@YAPEAX_K@Z            00000001800b022c f   ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll
 0001:000af232       ??_V@YAXPEAX@Z             00000001800b0232 f   ABQSMABasCoreUtils_import:ABQSMABasCoreUtils.dll

If I undecorate those names using "undname" they give the following (same order):

void __cdecl operator delete(void * __ptr64)
void * __ptr64 __cdecl operator new(unsigned __int64)
void * __ptr64 __cdecl operator new[](unsigned __int64)
void __cdecl operator delete[](void * __ptr64)

I am not sure I understand how anything from ABQSMABasCoreUtils.dll can exist within this .map file or why my DLL is even attempting to load ABQSMABasCoreUtils.dll if I don't have any code that references this DLL. Can anyone help me put this information together and find out why this isn't working? For what it's worth I have confirmed via "dumpbin" that the parent application imports ABQSMABasCoreUtils.dll, so it is being loaded no matter what. I have also tried delay loading this DLL in my DLL but that did not change the results.

EDIT

I have double checked and all files involved are 64 bit.

brady
  • 2,227
  • 16
  • 18
  • 1
    Do you tried use `LoadLibrary` instead of static linking of the import library? If you do this, you main application is already initialized and you have so some advantage. – Oleg May 27 '10 at 23:39
  • I thought of that but I will end up using a large amount of functions from this library. Won't I have to use GetProcAddress for each one? I'd prefer to avoid that if possible. – brady May 27 '10 at 23:50
  • 1
    C0000025 = STATUS_NONCONTINUABLE_EXCEPTION. Try running the application in windbg and see where it crashes; maybe that will give you a hint. – Luke May 28 '10 at 02:35

4 Answers4

5

I just had exactly the same problem. This is an issue with the Abaqus API rather than with the loading of DLLS.

I think it is because the Abaqus API overrides the new and delete functions (as you seem to have noticed). If you call new or delete in your program before initializing the Abaqus API, such as by calling odb_initializeAPI(); then you get the

ERROR: Memory allocation attempted before component initialization

error message and the program crashes.

In my program, calling odb_initializeAPI(); before the first new resolved the problem.

David Dibben
  • 18,460
  • 6
  • 41
  • 41
  • 1
    It's been awhile since I fixed this but I had a bit of a different problem. I was actually accessing the ODB in a user subroutine so I was using getActiveOdb(). I was getting this error because I was compiling with a dependency on msvcr90.dll and Abaqus was using msvcr80.dll. But I'm glad you posted the above - it's tough to find quick help online for Abaqus user subroutines and post processors. – brady Nov 14 '10 at 14:49
  • @brady How did you identify and fix the dependency issue? I believe that `msvcr100.dll` is conflicting with `msvcr80.dll` in my program. I would really appreciate some help with this. – Derek Sep 10 '12 at 18:45
  • 1
    I don't remember how I identified it - I probably used the "dumpbin /imports" utility and noticed the redundant C++ runtime libraries. To fix the problem, I had to build with Visual C++ 8.0 (Visual Studio 2005) which was the supported C++ compiler for that version of Abaqus. You can view supported compilers here: [Abaqus System Requirements](http://www.3ds.com/support/certified-hardware/simulia-system-information/). Choose the appropriate version and click System Requirements, choose your platform, and look for the C++ Compiler requirements. – brady Sep 11 '12 at 04:08
  • @brady I am using Visual Studio 2010. I installed a little utility called Daffodil which enables you to link to older versions of the CRT libraries (VS 2010 supports native multi-targeting). I ran Dependency Walker and the only CRT library included is v80 (msvcr80.dll). I thought that this would solve my problem, but I still can't get the program to run. The stack trace from the debugger shows that the program crashes inside of an Abaqus DLL. – Derek Sep 11 '12 at 14:32
  • @Derek maybe it's crashing due to another reason. Does the function it's crashing in give any hints? Are you accessing the ODB from a user subroutine or are you creating your own post processing executable? If the latter, I would recommend you use the `abaqus make` utility. Also, from someone who's done a lot of interfacing with Abaqus (user subs, exes, Python, etc.) on Windows and Linux, it is a really good idea to use the supported compilers if at all possible. Especially as your build gets more and more complicated and relies on more libraries, etc. – brady Sep 13 '12 at 13:50
  • @brady Thank you so much for all of your comments. We have a different ODB interface that uses an "unsupoprted" compiler, which confuses me, but that is beside the point. I finally figured out that we have a static factory object that is being dynamically allocated before anything in the main file is running. I've been trying to learn about how this works. I made the mistake of thinking that nothing would be allocated before the first line of the main file. Now I need to figure out how to initialize the API before this static object. – Derek Sep 13 '12 at 13:58
  • I fixed my problem! See http://stackoverflow.com/questions/12408787/call-a-function-before-static-member-allocation for details. – Derek Sep 14 '12 at 15:18
2

Well, sure you'll reference the imports of that library. Hard to write a C++ program without using the new or delete operator. Dealing with 3rd party software that thinks it needs to override the CRT version of those operators is hard enough, impossible when it won't allow you to call them until it thinks the time is right. Abandon all hope or seek help from the vendor.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    Is it common for large C++ programs to override such common operators? That seems pretty silly. Is it possible to get around this with /DEFAULTLIB? – brady May 27 '10 at 23:57
  • 2
    It is only common in silly programs and foundation style class libraries that count on all code getting linked with them. You cannot get around it. Hacking the .lib will only bring grief when some code uses the allocator and other code doesn't. That's an automatic memory leak or AV. – Hans Passant May 28 '10 at 00:13
1

One of the possible reason of an error during loading of ABQSMABasCoreUtils.dll is that some dependency module (inclusive delayed load DLLs) could not be found. Use Dependency Walker (see http://www.dependencywalker.com/) to examine all dependencies of ABQSMABasCoreUtils.dll.

I have two suggestions:

  1. Verify that you can load ABQSMABasCoreUtils.dll with respect of LoadLibrary. You don't need call any function from ABQSMABasCoreUtils.dll. Usage of LoadLibrary I don't see as the end solution. It' s only a diagnostic test. With the test you can verify either you have some general problem of loading ABQSMABasCoreUtils.dll in your program or you have some kind of process initialization problem.
  2. If loading of ABQSMABasCoreUtils.dll with respect of LoadLibrary will failed, then use profiling feature of Dependency Walker to protocol of all calls done during loading of ABQSMABasCoreUtils.dll. One other way would be usage of Process Monitor (see http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) to trace what file and registry operations will be done during loading of ABQSMABasCoreUtils.dll.

If LoadLibrary is not failed, then you have really an initialization problem of DLLs. Typically the problem exist if a DLL inside of DllMain try use a function from another DLL which is not yet initialized (not yet returns from DllMain). Before one start diagnostic of this problem, we should try to exclude a more simple problems with LoadLibrary.

Oleg
  • 220,925
  • 34
  • 403
  • 798
0

The ABQSMABasCoreUtils.dll looks like it's importing 64-bit functions. Is your dll also 64-bit? If not, then that's the problem - you cannot mix DLLs compiled for different architectures in the same process.

mdma
  • 56,943
  • 12
  • 94
  • 128