Jump to content

  • Log In with Google      Sign In   
  • Create Account


Multithreaded DLLs and Debug vs Release


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 Servant of the Lord   Crossbones+   -  Reputation: 17310

Like
0Likes
Like

Posted 07 February 2013 - 10:31 PM

I'm using MinGW 4.7.2
 
When compiling DLLs, a DLL can either be single-threaded or multithreaded, right? And it can either be a debug or release build, right?
 
When compiling an executable, every DLL connected to it must be the same thread type (single vs multithreaded) and the same build type (debug vs release), correct?
 
I've recently (~1 month ago) upgraded my compiler to the latest version and rebuilt all the third-party libraries I use. I'm receiving really weird crashes during the static initialization phase. Currently I'm crashing in the standard <iostream> header at this line:
 
// For construction of filebuffers for cout, cin, cerr, clog et. al.
static ios_base::Init __ioinit;
I've built the Boost libraries as 'multithreaded DLLs', and I don't know if I built the other third-party libraries with that or not.
What is the difference between 'multithreaded DLLs' and regular DLLs? How do I check if a DLL is multithreaded or not?

Edited by Servant of the Lord, 07 February 2013 - 10:36 PM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


Sponsor:

#2 Servant of the Lord   Crossbones+   -  Reputation: 17310

Like
0Likes
Like

Posted 07 February 2013 - 10:44 PM

(bleh, attempting to recreate the portion of my post that got lost when I hit 'post')

I think it's the boost library that's causing the crash, because my stack trace looks like this:

0	strchr	C:\Windows\system32\msvcrt.dll		0x756ddc12	
1	libstdc++-6!_ZGVNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fccb5c0	
2	??			0x22fd24	
3	libstdc++-6!_ZNSt5ctypeIwEC2Ej	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fcabebc	
4	libstdc++-6!_ZNSt6locale5_ImplC2Ej	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fcae5d6	
5	libstdc++-6!_ZNSt6locale11_M_coalesceERKS_S1_i	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fcac650	
6	libstdc++-6!__cxa_demangle	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fc4daea	
7	libstdc++-6!__dynamic_cast	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fcbf042	
8	libstdc++-6!_ZNSt6locale11_M_coalesceERKS_S1_i	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fcac610	
9	libstdc++-6!_ZNSt6localeC2Ev	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fcafa5b	
10	libstdc++-6!_ZNSt15basic_streambufIcSt11char_traitsIcEEC2Ev	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fca191f	
11	libstdc++-6!_ZN9__gnu_cxx18stdio_sync_filebufIcSt11char_traitsIcEEC1EP6_iobuf	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fc5bd1f	
12	libstdc++-6!_ZNSt8ios_base4InitC2Ev	D:\MinGW\4.7.2\bin\libstdc++-6.dll		0x6fcb0ff1	
13	__static_initialization_and_destruction_0	iostream	75	0x68dc2107	
14	_GLOBAL__sub_I__ZN5boost6system6throwsE	error_code.cpp	430	0x68dc2157	
15	__do_global_ctors	D:\MinGW\4.7.2\bin\libboost_system-mt-d.dll		0x68dc268a	
16	DllMainCRTStartup@12	D:\MinGW\4.7.2\bin\libboost_system-mt-d.dll		0x68dc110b	
17	VerifierGetProviderHelper	C:\Windows\system32\verifier.dll		0x6d5ec66d	
18	vrfcore!VerifierTlsSetValue	C:\Windows\SYSTEM32\vrfcore.dll		0x6d7d898c	
19	??	C:\Windows\SYSTEM32\vfbasics.dll		0x6d71f544	
20	wcstol	C:\Windows\system32\ntdll.dll		0x76e78968	
21	ntdll!EtwRegisterSecurityProvider	C:\Windows\system32\ntdll.dll		0x76e85c11	
22	ntdll!LdrShutdownProcess	C:\Windows\system32\ntdll.dll		0x76e86145	
23	ntdll!LdrShutdownProcess	C:\Windows\system32\ntdll.dll		0x76e86047	
24	ntdll!LdrResFindResource	C:\Windows\system32\ntdll.dll		0x76e835e9	
25	??				
...	More

Frame 14 is the one the debugger brings me to (above that is assembly, I guess).
Frame 15 is a boost library, libboost_system-mt-d.dll

If I right-click in my IDE (QtCreator) and do 'Create Full Stacktrace' it looks like this:

//Portion of it I snipped away.

#12 0x6fcb0ff1 in libstdc++-6!_ZNSt8ios_base4InitC2Ev () from D:\MinGW\4.7.2\bin\libstdc++-6.dll
No symbol table info available.
#13 0x68dc2107 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at d:/mingw/latest/bin/../lib/gcc/mingw32/4.7.2/include/c++/iostream:75
No locals.
#14 0x68dc2157 in _GLOBAL__sub_I__ZN5boost6system6throwsE () at libs\system\src\error_code.cpp:430
No locals.
#15 0x68dc268a in __do_global_ctors () from D:\MinGW\4.7.2\bin\libboost_system-mt-d.dll
        std::__ioinit = {static _S_refcount = <optimized out>, static _S_synced_with_stdio = <optimized out>}
        boost::system::posix_category = @0x0: <error reading variable>
        boost::system::errno_ecat = @0x0: <error reading variable>
        boost::system::native_ecat = @0x0: <error reading variable>
        boost::system::throws = {m_val = 0, m_cat = 0x0}
#16 0x68dc110b in DllMainCRTStartup@12 () from D:\MinGW\4.7.2\bin\libboost_system-mt-d.dll
No symbol table info available.
#17 0x6d5ec66d in VerifierGetProviderHelper () from C:\Windows\system32\verifier.dll
No symbol table info available.
#18 0x6d7d898c in vrfcore!VerifierTlsSetValue () from C:\Windows\SYSTEM32\vrfcore.dll
No symbol table info available.	

//Portion of it I snipped away.

I don't actually use multithreaded code in my project.
Should I be building all the third-party libraries as multithreaded DLLs anyway?
How do I check if a DLL I already compiled is multithreaded or not?
Should I just rebuild boost as singlethreaded?
 
I know I built boost as multithreaded (hence the 'mt' in the DLL name) and I built both debug and release builds for boost and every DLL I use.


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#3 Hodgman   Moderators   -  Reputation: 27913

Like
7Likes
Like

Posted 07 February 2013 - 10:57 PM

When compiling DLLs, a DLL can either be single-threaded or multithreaded, right? And it can either be a debug or release build, right?
When compiling an executable, every DLL connected to it must be the same thread type (single vs multithreaded) and the same build type (debug vs release), correct?
What is the difference between 'multithreaded DLLs' and regular DLLs?

Uh, kind of, not really.
The DLL itself isn't affected by these settings (i.e. there's no such thing as a multithreaded DLL/EXE vs a singlethreaded DLL/EXE) - what you're talking about is the version of the C++ runtime (C and C++ standard libraries) that your DLL/EXE is linked against. As well as linking against the runtime as either single-threaded/thread-safe debug/release DLLs, you've also got the choice of linking to the single/thread-safe debug/release static-library versions of the runtime too... So that's 3 binary choices, leading to 8 different versions of the runtime that you can choose from.

Trouble appears when different parts of your program (different DLLs/EXEs/libs) are linked against different versions of the runtime, especially if standard objects are shared between these different parts of your program. Sometimes these conflicts straight up cause your program to fail at the linker step due to conflicts, other times it successfully links but crashes on startup due to a mixture of runtimes operating on the same objects (with different layouts), and sometimes it crashes later when you're calling code that crosses a module boundary...

I don't actually use multithreaded code in my project.
Should I be building all the third-party libraries as multithreaded DLLs anyway?

Yeah you should probably use the multithreaded (i.e. thread-safe) versions, as they're the most common choice. If you ever integrate some middleware in the future that does require the use of multiple threads, then you might be forced to use the MT version of the runtime at that point anyway.

I've built the Boost libraries as 'multithreaded DLLs', and I don't know if I built the other third-party libraries with that or not.
How do I check if a DLL is multithreaded or not?

It's a pain of C++ that you'll need to rebuild all of your 3rd party code to use the same version of the runtime, or trust the 3rd party provider that they've used the same version as you have. To be safe, go back and rebuild all your 3rd party code... unsure.png 
I'm not sure how to check which version has been linked in... I guess by inspecting the symbols in the library you could find out... I usually just check the build configuration that was used to generate the exe/lib/dll in the first place.


Edited by Hodgman, 07 February 2013 - 11:08 PM.


#4 Servant of the Lord   Crossbones+   -  Reputation: 17310

Like
0Likes
Like

Posted 07 February 2013 - 11:10 PM

Even when using MinGW, the 'standard runtime' would be MSVCRT.DLL it seems.

 

Are there different names for the debug vs release version or single-threaded vs multithreaded versions of MSVCRT.DLL that I could perhaps check using Dependency Walker on the DLLs I've compiled? If there's a debug and a release MSVCRT.dll, it either has to have a different name or be located in a different file...

 

[Edit:] Ah hah, MSVCRT.DLL vs MSVCRTD.DLL and so on.

 

It seems like:

MSVCRT = Multithreaded Dynamic Runtime

MSVCRTD = Multithreaded Dynamic Debug Runtime
 
LIBCMT = Multithreaded Static Runtime
LIBCMTD = Multithreaded Static Debug Runtime
 
I don't see the non-multithreaded names, but if a DLL is named something other than MSVCRT or MSVCRTD, I guess I'll know which is the problem.
 
[Edit 2:] Nope, all the 'MSVCRT' vs 'MSVCRTD' is staticly compiled into the DLLs, and then calls into MSVCRT anyway(?), so even the very clearly 'debug' version of the third-party DLLs all link against MSVCRT and not MSVCRTD. sad.png

Edited by Servant of the Lord, 07 February 2013 - 11:27 PM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#5 Ashaman73   Crossbones+   -  Reputation: 6759

Like
0Likes
Like

Posted 08 February 2013 - 12:04 AM

I'm not sure how to check which version has been linked in...

Dependency walker shoud do the job, atleast if the runtime libs are not statically linked in.



#6 Servant of the Lord   Crossbones+   -  Reputation: 17310

Like
0Likes
Like

Posted 08 February 2013 - 12:05 AM

Grr, it compiled and ran just now in release mode without crashing (that is, without crashing before 'main()' - but that's an unrelated crash).

 

*sigh* So it must be some kinda of static initialization order issue after all. I don't see where, though!

I have a few global std::unique_ptrs, but I don't initialize them until after main() enters, so their dependencies on each other can't possibly clash, and even if they did, the unique_ptrs would throw.

 

Somehow, the debug build crashes before main() is entered, and the release build does not.


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#7 larspensjo   Members   -  Reputation: 1526

Like
1Likes
Like

Posted 08 February 2013 - 01:41 AM

Somehow, the debug build crashes before main() is entered, and the release build does not.

 

I had this problem recently. It happened when I upgraded the gcc version in MinGW from 4.6 to 4.7. Some of the third party libraries I use was compiled with gcc 4.6, and some with 4.7, and I think there are incompatibilities. When I made sure to recompile everything with 4.7, it worked.

 

To be more specific, it seems to be a compatibility problem with the constructor of global objects. You can be hit by this if you use external libraries that have globall C++ objects.


Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

#8 wintertime   Members   -  Reputation: 1615

Like
1Likes
Like

Posted 08 February 2013 - 08:08 AM

Yes, there is a warning in the changelog of gcc 4.7 that it will be binary incompatible with 4.6. Even 4.7.1 in C++11 mode would be incompatible with itself in C++03 mode, but that bug is possibly fixed in 4.7.2 (not completely sure about if its really fixed). This is what kept me away from the upgrade for a long time.



#9 Servant of the Lord   Crossbones+   -  Reputation: 17310

Like
0Likes
Like

Posted 08 February 2013 - 01:51 PM

I did recompile everything - but I'll try again, maybe I missed something.


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#10 Servant of the Lord   Crossbones+   -  Reputation: 17310

Like
0Likes
Like

Posted 13 February 2013 - 05:08 PM

Okay, I recompiled everything and now it compiles and runs fine. I must've missed some DLL or other.

 

Thanks for all the help gents!


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS