I debug an application which links against two DLLs. When an object from one of these DLLs is instantiated the application segfaults. However, when the order of the .lib files in (VS2010) Linker->Input->Additional Dependencies is swapped then the application runs fine.
This workaround works for now but I still want to understand what caused the problem. Any hints, how can I further debug this?
While without much more information any answer is bound to be a speculation, one potential reason is the following:
in Windows, every DLL has DLLMain() function
as soon as you have two DLLs, they will have two DllMain() function calls
if there is a dependency between the two (i.e. one DLLMain() implicitly relies on an object being initialized within another one) - you have a problem.
I've seen such a problem myself (which is obviously a bad programming practice, but it does happen). However, a number of other explanations may also exist.
The way to debug this would be the way to debug any crash: start by inspecting the stack at the catch of the segfault. If the crash reproduces at debug builds, understanding the direct reason should be straightforward (the root cause usually takes some deeper investigation).
Not much can be said about the cause of the crash without viewing this stack, but it is reasonable to assume that a global resource is involved. A named event, common temporary file, perhaps some internal framework structure (which, if any, frameworks are involved in your code?) - but it must be something that crosses the individual DLL boundaries, and so is probably a resource at application scope.
Related
I have a strange issue that I am trying to work out for someone. I don't have any access to the code. There is a program that loads a DLL and has somewhat of a plugin framework. They provide virtually no documentation beyond how to import functions from the DLL and what calling convention to use for exports.
This person's plugin imports functions from a DLL (let's assume they used the proper calling conventions and imported properly). It periodically runs into access violations (usually access violation write/read from 0x0000000). Sometimes, it crashes the program and Event Viewer shows exception code 0xc0000005 (another access violation) with faulting module SHLWAPI.dll.
Using depends, I have determined that the program is statically linked to msvcr. I found that the plugin DLL dynamically links to msvcr120.dll.
Yes, I am aware that this is just asking for trouble and the access violations are no surprise, but unfortunately, I have to deal with someone else's problem.
Anyway, my question is this:
Let's say is imported from this DLL and inside is a call to a function that is provided by msvcr120. When the program calls the imported , is it possible that it is calling from the msvcr it is statically linked to rather than from msvcr120?
I realize that it probably depends on the main program's plugin framework, but general feedback would be appreciated.
Thanks in advance!
There are known issues when using multiple copies of the CRT in one program, even when they all use the same version of the CRT (see Potential Errors Passing CRT Objects Across DLL Boundaries). If the CRTs are different versions, there are lots of other problems due to different size or layout of internal structures.
Since the program you use statically links with the CRT, it can not reliably be plugged in to. The anti-debugger code is just plain silly; there are several ways around it. If you paid for it send it back and demand a refund.
I am facing a rather peculiar issue: I have a Qt C++ application that used to work fine. Now, suddenly I cannot start it anymore. No error is thrown, no nothing.
Some more information:
Last line of output when application is started in debug mode with Visual Studio 2012:
The program '[4456] App.exe' has exited with code -1 (0xffffffff).
Actual application code (= first line in main()) is never called or at least no breakpoints are triggered, so debugging is not possible.
The executable process for a few seconds appears in the process list and then disappears again.
Win 7 x64 with latest Windows updates.
The issues simultaneously appeared on two separate machines.
Application was originally built with Qt 5.2.1. Today I test-wise switched to Qt 5.4.1. But as expected no change.
No changes to source code were made. The issue also applies to existing builds of the application.
Running DependencyWalker did not yield anything of interest from my point of view.
I am flat out of ideas. Any pointers on what to try or look at? How can an executable suddenly stop working at all with no error?
I eventually found the reason for this behavior...sort of. The coding (e. g. my singletons) were never the problem (as I expected since the code always worked). Instead an external library (SAP RFC SDK) caused the troubles.
This library depends on the ICU Unicode libraries and apparently specific versions at that. Since I wasn't aware of that fact, I only had the ICU libraries that my currently used Qt version needs in my application directory. The ICU libraries for the SAP RFC SDK must have been loaded from a standard windows path so far.
In the end some software changes (Windows updates, manual application uninstalls, etc.) must have removed those libraries which resulted in that described silent fail. Simply copying the required ICU library version DLLs into my application folder, solved the issue.
The only thing I am not quite sure about, is why this was not visible when tracing the loaded DLLs via DependencyWalker.
"Actual application code (= first line in main()) is never called. So debugging is not possible."
You probably have some static storage initialization failing, that's applied before main() is called.
Do you use any interdependent singletons in your code? Consolidate them to a single singleton if so (remember, there shouldn't be more than one singleton).
Also note, debugging still is possible well for such situation, the trap is ,- for such case as described in my answer -, main()'s bodies' first line is set as the first break point as default, when you start up your program in the debugger.
Nothing hinders you to set breakpoints, that are hit before starting up the code reaches main() actually.
As for your clarification from comments:
"I do use a few singletons ..."
As mentioned above, if you are really sure you need to use a singleton, use actually a single one.
Otherwise you may end up, struggling with undefined order of initialization of static storage.
Anyway, it doesn't matter that much if static storage data depends on each other, provide a single access point to it throughout your code, to avoid cluttering it with heavy coupling to a variety of instances.
Coupling with a single instance, makes it easier to refactor the code to go with an interface, if it turns out singleton wasn't one.
We have a lot of executables that reference one of our dlls. We found a bug in one of our dlls and don't want to have to re-compile and redistribute all of our executables to fix it.
My understanding is that dlls will keep their compatibility with their executables so long as you don't change anything in the header file. So no new class members, no new functions, etc... but a change to the logic within a function should be fine. Is this correct? If it is compiler specific, please let me know, as this may be an issue.
Your understanding is correct. So long as you change the logic but not the interface then you will not run into compatibility issues.
Where you have to be careful is if the interface to the DLL is more than just the function signatures. For example if the original DLL accepted an int parameter but the new DLL enforced a constraint that the value of this parameter must be positive, say, then you would break old programs.
This will work. As long as the interface to the DLL remains the same, older executables can load it and use it just fine. That being said, you're starting down a very dangerous road. As time goes by and you patch more and more DLLs, you may start to see strange behaviour on customer installations that is virtually impossible to diagnose. This arises from unexpected interactions between different versions of your various components. Historically, this problem was known as DLL hell.
In my opinion, it is a much better idea to rebuild, retest, and redistribute the entire application. I would even go further and suggest that you use application manifests to ensure that your executables can only work with specific versions of your DLLs. It may seem like a lot of work now, but it can really save you a lot of headaches in the future.
It depends
in theory yes, if you load the dll with with LoadLibrary and haven't changed the interface you should be fine.
If you OTOH link with the .dll file using some .lib stub there is no guarantee it will work.
That is one of the reasons why COM was invented.
I have been provided with a C++ DLL and associated header file in order to integrate it with my application. To begin with, I am simply trying to call the DLL from a simple Win32 console application (I'm using Visual Studio 2008 Express).
I've linked the DLL by specifying it as an additional dependency in the project settings.
The interface (i.e. the only exported function) simply returns a pointer to an instance of the Class that I actually need to call. I can successfully call this, get the pointer and call the first function that I need to (an "init" function).
When I come to call the function that actually does the processing I require, I'm intermittently getting a "0xC0000005: Access violation reading location...." error. That is, I run the program - it works successfully and exits - I try to run it again (changing nothing - all parameters are hard coded) and get the error (and continue to do so).
I can't consistently recreate the problem but I'm beginning to think that it may be something to do with the DLL not being unloaded properly - after getting the error on one occasion I tried deleting the DLL and was told by Windows that it was in use. That said, on another occasion I was able to delete the DLL after getting the error, copy it back, then still got the error on the next run.
Should the DLL be correctly unloaded when my .exe finishes? Would I be better off trying to explicitly load/unload the DLL rather than doing it implicitly?
Any other help or advice greatly appreciated.
It won't have anything to do with the DLL being unloaded; different processes using the same DLL do not share any state. Also, the DLL will be unloaded when the process exits; perhaps not gracefully, but it will be unloaded.
I can think of two likely reasons for an intermittent failure.
Most likely, the DLL has a race condition. This could be one that's exposed if the DLL has been cached, causing the timing to change. That would explain why your first run didn't fail but subsequent ones did.
I think it's also possible that the DLL didn't release its lock on some file. If there is some file you know is accessed by this DLL, try checking to see if that file is locked after the process ends.
Also, get this in a debugger. Turn on first-chance exceptions in visual studio and look at the callstack where the AV is happening, and post it here.
What types are involved in the classes exported by the DLL? We have often had these kinds of problems with Visual Studio when the classes make use of STL - I'd guess that any template usage would probably be a way to potentially cause this sort of problem.
What's your setting for "Runtime library" under "C/C++" in the configuration properties?
You should probably try /MD (or /MDd for debugging).
see http://msdn.microsoft.com/en-us/library/2kzt1wy3(VS.71).aspx
Yesterday, I got bit by a rather annoying crash when using DLLs compiled with GCC under Cygwin. Basically, as soon as you run with a debugger, you may end up landing in a debugging trap caused by RtlFreeHeap() receiving an address to something it did not allocate.
This is a known bug with GCC 3.4 on Cygwin. The situation arises because the libstdc++ library includes a "clever" optimization for empty strings. I spare you the details (see the references throughout this post), but whenever you allocate memory in one DLL for an std::string object that "belongs" to another DLL, you end up giving one heap a chunk to free that came from another heap. Hence the SIGTRAP in RtlFreeHeap().
There are other problems reported when exceptions are thrown across DLL boundaries.
This makes GCC 3.4 on Windows an unacceptable solution as soon as your project is based on DLLs and the STL. I have a few options to move past this option, many of which are very time-consuming and/or annoying:
I can patch my libstdc++ or rebuild it with the --enable-fully-dynamic-string configuration option
I can use static libraries instead, which increases my link time
I cannot (yet) switch to another compiler either, because of some other tools I'm using. The comments I find from some GCC people is that "it's almost never reported, so it's probably not a problem", which annoys me even more.
Does anyone have some news about this? I can't find any clear announcement that this has been fixed (the bug is still marked as "assigned"), except one comment on the GNU Radio bug tracker.
Thanks!
The general problem you're running into is that C++ was never really meant as a component language. It was really designed to be used to create complete standalone applications. Things like shared libraries and other such mechanisms were created by vendors on their own. Think of this example: suppose you created a C++ component that returns a C++ object. How is the C++ component know that it will be used by a C++ caller? And if the caller is a C++ application, why not just use the library directly?
Of course, the above information doesn't really help you.
Instead, I would create the shared libraries/DLLs such that you follow a couple of rules:
Any object created by a component is also destroyed by the same component.
A component can be safely unloaded when all of its created objects are destroyed.
You may have to create additional APIs in your component to ensure these rules, but by following these rules, it will ensure that problems like the one described won't happen.