From: Paul L. <sa2...@cy...> - 2011-03-11 09:34:20
|
I'm moving a project from 3.4 to 4.5. The first surprise was that I needed a libstdc++-6.dll; we've never distributed any dlls previously, despite linking dynamically. The problem was that the exe silently failed when running in a Cygwin window. When running in cmd.exe, I got a pop-up complaining about a missing __gxx_personality_v0. I tracked this down to the fact that this machine had two libstdc++-6.dll's on it. Ok, here's the real problem: ---------------------------- I've compiled this app (A) with the current MinGW auto-installer native binaries, downloaded yesterday. However, users of app A also generally use app B in the same flow. App B is cross-compiled with mingw-w64 (the current one, from an auto build at MinGW-w64 on sourceforge), and comes with it's own libstdc++-6.dll. The two dlls are incompatible. If I hide dll B, then app A runs; if I hide dll A, then app B runs; I can't get both apps to run together, so I can't run the flow. Have I misunderstood something? It seems to me that this makes dynamic linking almost unusable. It's not just MinGW vs. MinGW-w64 - if your machine happens to have an incompatible dll in your path, ahead of your own dll, then you're in trouble. This is going to make support a nightmare, and means that you can't run incompatible apps together, and can only ever run specific apps by messing with paths each time. Another couple of questions, if you don't mind: 1 - I'm a bit hazy on why I've never seen a requirement for distributing various dlls before. Is this new with 4.4/4.5, and why? The website still says that mingw does "not depend on any 3rd-party C-Runtime DLLs". It would be nice to see something on the website (have I missed it?) - about the internals of turning libc calls into msvcrt, or whatever, and why extra dlls are required. 2 - I hesitate to ask, but there now appear to be licensing issues associated with distributing current mingw- or mingw-w64-compiled binaries together with the required dlls, which didn't exist with 3.4. I've spent a lot of time on Google, and found no consistent, or even comprehensible, answers. Can someone here attempt to answer this? If I distribute my binary with your dlls, am I under any obligations? Is there anything in your dlls which is viral, in the sense that it forces its own licensing requirements onto *my* code? Does it make any difference if I link statically instead? The 'Licensing Terms' webpage doesn't cover this, unless the dlls are part of "the MinGW base runtime package" (are they?) Many thanks - Paul |
From: Earnie <ea...@us...> - 2011-03-11 13:18:04
|
Paul Leder wrote: > I'm moving a project from 3.4 to 4.5. The first surprise was that I > needed a libstdc++-6.dll; we've never distributed any dlls previously, > despite linking dynamically. > > The problem was that the exe silently failed when running in a Cygwin > window. When running in cmd.exe, I got a pop-up complaining about a > missing __gxx_personality_v0. I tracked this down to the fact that this > machine had two libstdc++-6.dll's on it. > > Ok, here's the real problem: > ---------------------------- An ugly workaround to the real problem is to put program A in a directory with its libstdc++-6.dll and put program B in another directory with its libstdc++-6.dll and then add the directories to PATH. Another workaround is to create static builds of both A and B. Another workaround is to rename both dll files something like mingw-libstdc++-6.dll and mingw64-libstdc++-6.dll and modify the specs file for each distributed compiler so that it uses the renamed dll. Another workaround, and probably the better, use only one distribution of compiler. Why do you need to use both? Other workarounds may exist. > > I've compiled this app (A) with the current MinGW auto-installer native > binaries, downloaded yesterday. However, users of app A also generally > use app B in the same flow. App B is cross-compiled with mingw-w64 (the > current one, from an auto build at MinGW-w64 on sourceforge), and comes > with it's own libstdc++-6.dll. The two dlls are incompatible. If I hide > dll B, then app A runs; if I hide dll A, then app B runs; I can't get > both apps to run together, so I can't run the flow. > > Have I misunderstood something? It seems to me that this makes dynamic > linking almost unusable. It's not just MinGW vs. MinGW-w64 - if your > machine happens to have an incompatible dll in your path, ahead of your > own dll, then you're in trouble. This is going to make support a > nightmare, and means that you can't run incompatible apps together, and > can only ever run specific apps by messing with paths each time. > I knew it was only a matter of time when something like this would happen. > Another couple of questions, if you don't mind: > > 1 - I'm a bit hazy on why I've never seen a requirement for distributing > various dlls before. Is this new with 4.4/4.5, and why? The website > still says that mingw does "not depend on any 3rd-party C-Runtime DLLs". > It would be nice to see something on the website (have I missed it?) - > about the internals of turning libc calls into msvcrt, or whatever, and > why extra dlls are required. > It wasn't until the gcc4 series that it was even possible to build a libstdc++ dll, so yes, it is new with that series. I wondered about the "not depend on any 3rd-party C-Runtime DLLs" phrase and in reality it has direct relation to the "C Runtime" MSVCRT.DLL vs something similar like CYGWIN1.DLL which replaces the MSVCRT.DLL but I understand why one might understand the phrase incorrectly. > 2 - I hesitate to ask, but there now appear to be licensing issues > associated with distributing current mingw- or mingw-w64-compiled > binaries together with the required dlls, which didn't exist with 3.4. > I've spent a lot of time on Google, and found no consistent, or even > comprehensible, answers. Can someone here attempt to answer this? If I > distribute my binary with your dlls, am I under any obligations? Is > there anything in your dlls which is viral, in the sense that it forces > its own licensing requirements onto *my* code? Does it make any > difference if I link statically instead? The 'Licensing Terms' webpage > doesn't cover this, unless the dlls are part of "the MinGW base runtime > package" (are they?) Well, the license page could be clearer I suppose, but it does state "Binutils, GCC, GDB, GNU Make: All of the GNU development tools, such as GNU binutils, GCC, GDB and GNU Make, are governed by the terms of the GNU General Public License." The libstdc++ library is part of GCC. However, there is special provision in the license for libstdc++ and we should add a reference to it's license page. Perhaps this link http://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html would suffice. You have the typical uneasy feeling you get when you try to be a lawful abiding citizen and want to meet the constraints placed on one without wanting to spend money on a lawyer to defend ones actions. The libstdc++ license grants you rights to use GCC to compile the library into independent code and not have that independent code governed by the GPL. However, distribution of the libstdc++ dll requires you to offer the source code for the version of the libstdc++ dll distributed via the same medium you distributed the library because that is what the GPL does. It is typical that the distribution have both the source and the binary versions just so that the obligation is met without the need to respond to queries separately. HTH, -- Earnie -- http://www.for-my-kids.com |
From: Paul L. <sa2...@cy...> - 2011-03-14 09:59:27
|
On 11/03/2011 13:17, Earnie wrote: > An ugly workaround to the real problem is to put program A in a > directory with its libstdc++-6.dll and put program B in another > directory with its libstdc++-6.dll and then add the directories to PATH. This doesn't work, although I don't yet understand why. PATH itself shouldn't be relevant here, as the app's installation directory should come up earlier in the dll search order anyway. I'm hoping to find out what's going on here tonight... > Another workaround is to create static builds of both A and B. I may have to do this, although the exception problem is worrying. > Another workaround is to rename both dll files something like > mingw-libstdc++-6.dll and mingw64-libstdc++-6.dll and modify the specs > file for each distributed compiler so that it uses the renamed dll. Ok, this may be the only long-term solution. However, it does reduce the usefulness of pre-built compiler binaries (to the point where they're *not* useful for dynamic builds??) > Another workaround, and probably the better, use only one distribution > of compiler. Why do you need to use both? Well, this is the real problem. I'm responsible for App 'foo'; App 'bar' isn't mine, and I don't compile it. There may be hundreds (Ok, 3 or 4) exes on my Windows box that I know nothing about, but which were build with MinGW, each of which has its own libstdc++. It doesn't matter (does it?) if some of them were compiled on mingw-w64, and some on mingw; what matters is if they require different libstdc++ versions. In my particular case, it so happens that the end-user runs 'foo' and 'bar' in the same flow, using a driver that I've written. >> 1 - I'm a bit hazy on why I've never seen a requirement for distributing >> various dlls before. Is this new with 4.4/4.5, and why? > > It wasn't until the gcc4 series that it was even possible to build a > libstdc++ dll, so yes, it is new with that series. So how was this handled in 3.4? I was doing dynamic builds without problems. Thanks - Paul |
From: Chris W. <ch...@qw...> - 2011-03-16 20:37:26
|
Hi Paul, On Mon, 14 Mar 2011, Paul Leder wrote: > On 11/03/2011 13:17, Earnie wrote: >> Another workaround, and probably the better, use only one distribution >> of compiler. Why do you need to use both? > > Well, this is the real problem. I'm responsible for App 'foo'; App 'bar' > isn't mine, and I don't compile it. There may be hundreds (Ok, 3 or 4) > exes on my Windows box that I know nothing about, but which were build > with MinGW, each of which has its own libstdc++. It doesn't matter (does > it?) if some of them were compiled on mingw-w64, and some on mingw; what > matters is if they require different libstdc++ versions. In general it's not possible to mix objects compiled with different C++ compilers in the same executable. Usually this is due to the lack of ABI standardisation, resulting in each compiler using a different ABI. That may not be the case here, but the maxim still holds: "Compile ALL your objects and libraries with the SAME compiler". Is there a really good reason why you can't compile your app "foo" with the same compiler that "bar" uses, i.e. the same version of mingw-w64? >>> 1 - I'm a bit hazy on why I've never seen a requirement for >>> distributing various dlls before. Is this new with 4.4/4.5, and why? >> >> It wasn't until the gcc4 series that it was even possible to build a >> libstdc++ dll, so yes, it is new with that series. > > So how was this handled in 3.4? I was doing dynamic builds without > problems. As far as I know, libstdc++ was (used to be) always statically linked even in dynamic builds, so you would not have had any version conflict between "foo" and "bar" since they both contained their own independent copies of the relevant parts of libstdc++, statically compiled in. Cheers, Chris. -- _____ __ _ \ __/ / ,__(_)_ | Chris Wilson <chr...@qw...> Cambs UK | / (_/ ,\/ _/ /_ \ | Security/C/C++/Java/Ruby/Perl/SQL Developer | \__/_/_/_//_/___/ | We are GNU : free your mind & your software | |
From: Paul L. <sa2...@cy...> - 2011-03-16 22:59:39
|
On 16/03/2011 20:37, Chris Wilson wrote: > In general it's not possible to mix objects compiled with different C++ > compilers in the same executable. Usually this is due to the lack of ABI > standardisation, resulting in each compiler using a different ABI. That > may not be the case here, but the maxim still holds: > > "Compile ALL your objects and libraries with the SAME compiler". > > Is there a really good reason why you can't compile your app "foo" with > the same compiler that "bar" uses, i.e. the same version of mingw-w64? They're not in the same executable - they're two completely separate executables; I'm responsible for AppA, but not for AppB. I can't, in general, compile AppB. I may not even know what AppB is, although I do in this case. There's no connection at all between the two, except that they both require libstdc++. I only know about the problem because a subset of users use both executables in the same flow. 1 - AppA is in dirA, together with some version of libstdc++. 2 - AppB is in dirB, together with some other version of libstdc++. 3 - AppA does not work until the version of libstdc++ in *dirB* is removed or renamed. But appA knows *nothing* about AppB or dirB, except that dirB is in the path. 4 - AppB does not work until the version of libstdc++ in *dirA* is removed or renamed. But AppB knows *nothing* about AppA or dirA, except that dirA is in the path. Yes, it's bizarre, but it's trivially reproducible. All I have to do is rename an unrelated libstdc++ to get one or the other of AppA or AppB to work. I've written a simple test case, based on Charles Wilson's code, that does work; it shows that 2 separate trivial apps in 2 separate directories will, in a simple case, work as expected: the required dll is picked up first from the directory that the app is located in, as expected, even if there's another dll of the same name. So, in general, my problem shouldn't exist. I haven't posted this test code, because I'm still trying to work out what's going in my more complex case, in my spare time. I hope to have an answer over the next few days. -Paul |
From: Greg C. <gch...@sb...> - 2011-03-16 23:29:02
|
On 2011-03-16 22:59Z, Paul Leder wrote: > > 1 - AppA is in dirA, together with some version of libstdc++. > > 2 - AppB is in dirB, together with some other version of libstdc++. > > 3 - AppA does not work until the version of libstdc++ in *dirB* is > removed or renamed. But appA knows *nothing* about AppB or dirB, except > that dirB is in the path. > > 4 - AppB does not work until the version of libstdc++ in *dirA* is > removed or renamed. But AppB knows *nothing* about AppA or dirA, except > that dirA is in the path. What happens if you remove dirA and dirB from $PATH, and invoke the programs with full paths, i.e., as dirA/AppA and dirB/AppB? |
From: Earnie <ea...@us...> - 2011-03-17 12:21:20
|
Greg Chicares wrote: > On 2011-03-16 22:59Z, Paul Leder wrote: >> >> 1 - AppA is in dirA, together with some version of libstdc++. >> >> 2 - AppB is in dirB, together with some other version of libstdc++. >> >> 3 - AppA does not work until the version of libstdc++ in *dirB* is >> removed or renamed. But appA knows *nothing* about AppB or dirB, except >> that dirB is in the path. >> >> 4 - AppB does not work until the version of libstdc++ in *dirA* is >> removed or renamed. But AppB knows *nothing* about AppA or dirA, except >> that dirA is in the path. > > What happens if you remove dirA and dirB from $PATH, and invoke the > programs with full paths, i.e., as dirA/AppA and dirB/AppB? > Will not help, the already loaded DLL will be used unless you use DLL Redirection. -- Earnie -- http://www.for-my-kids.com |
From: Earnie <ea...@us...> - 2011-03-17 12:17:00
|
Paul Leder wrote: > On 16/03/2011 20:37, Chris Wilson wrote: > >> In general it's not possible to mix objects compiled with different C++ >> compilers in the same executable. Usually this is due to the lack of ABI >> standardisation, resulting in each compiler using a different ABI. That >> may not be the case here, but the maxim still holds: >> >> "Compile ALL your objects and libraries with the SAME compiler". >> >> Is there a really good reason why you can't compile your app "foo" with >> the same compiler that "bar" uses, i.e. the same version of mingw-w64? > > They're not in the same executable - they're two completely separate > executables; I'm responsible for AppA, but not for AppB. I can't, in > general, compile AppB. I may not even know what AppB is, although I do > in this case. Try the following, don't know if it works but worth experimentation based on links I have earlier in this thread and reference below. In the directory containing AppA.exe create a directory AppA.exe.local and do the same for AppB.exe. Sounds stupid but is used to do what is dubbed by Microsoft as DLL redirection which causes an already loaded DLL to be ignored. http://msdn.microsoft.com/en-us/library/ms682586(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/ms682600(v=vs.85).aspx -- Earnie -- http://www.for-my-kids.com |
From: Earnie <ea...@us...> - 2011-03-17 12:45:39
|
Martin Mitáš wrote: > > Hi. > > Perhaps this could help you: > http://msdn.microsoft.com/en-us/library/ms682586%28v=vs.85%29.aspx > > Maybe your apps use the alternate search path, use SetDllDirectory, > specify the DLL in its manifest or some other similar stuff? Also > check the app you don't know anything about does not e.g. install > some binaries into C:\Windows or other system directory (either in > install time, or during runtime) or adds it into registry somewhere > (e.g. HKLM\SYSTEM\CurrentControlSet\Control\Session > Manager\KnownDLLs). But that SetDllDirectory will not help enough since it doesn't eliminate the check of an already loaded DLL. However, DLL Redirection will help based on the documentation. http://msdn.microsoft.com/en-us/library/ms682600(v=vs.85).aspx <http://msdn.microsoft.com/en-us/library/ms682600%28v=vs.85%29.aspx> Earnie |
From: John B. <joh...@ho...> - 2011-03-14 14:26:07
|
On Mon, 14 Mar 2011 08:21:09 -0400, Earnie wrote: > > Maybe the base address is the same for both libraries and therefore has > memory collision? As I understand Windows workings, if the dll is in > the same directory as the binary then that dll would be used. But if > both dll have the same entry point then there will be collision. > My understanding is that Windows first checks to see if the DLL is already loaded. If it is, then the .exe will use the loaded copy. I could be wrong. It is described somewhere in the Windows Programmer's Reference, but I'm lazy. Regards, Alias John Brown. |
From: Earnie <ea...@us...> - 2011-03-14 20:57:20
|
John Brown wrote: > > On Mon, 14 Mar 2011 08:21:09 -0400, Earnie wrote: > >> >> Maybe the base address is the same for both libraries and therefore has >> memory collision? As I understand Windows workings, if the dll is in >> the same directory as the binary then that dll would be used. But if >> both dll have the same entry point then there will be collision. >> > > My understanding is that Windows first checks to see if the DLL is > already loaded. If it is, then the .exe will use the loaded copy. > I could be wrong. It is described somewhere in the Windows Programmer's > Reference, but I'm lazy. > I also found these: http://msdn.microsoft.com/en-us/library/ms682586(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/ms682600(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/aa375365(v=vs.85).aspx Which may help resolve the issue. -- Earnie -- http://www.for-my-kids.com |
From: Charles W. <cwi...@us...> - 2011-03-14 17:02:23
Attachments:
dlltest.tar.bz2
|
On 3/14/2011 12:16 PM, K. Frank wrote: > I'm speaking from memory from many years ago, but my understanding > is that different dll's with the same name -- that is, the same file name, > but residing in different directories -- count as different dll's from the > perspective of reusing an already-loaded dll. Nope. Here's a test case: unpack, then (cd dlltest/lib && make) (cd dlltest/app && make) (cd dlltest/app && make test) You'll get this output: This is app/a_foo app called app/a_foo: 1 This is lib/b_foo, calling lib/a_foo... This is app/a_foo app called lib/b_foo: 2 This shows that app/cyga.dll is being loaded to satisfy lib/cygb.dll's need for cyga.dll -- and NOT lib/cyga.dll. -- Chuck |
From: K. F. <kfr...@gm...> - 2011-03-14 18:59:29
|
Hello Chuck! On Mon, Mar 14, 2011 at 1:02 PM, Charles Wilson wrote: > On 3/14/2011 12:16 PM, K. Frank wrote: >> I'm speaking from memory from many years ago, but my understanding >> is that different dll's with the same name -- that is, the same file name, >> but residing in different directories -- count as different dll's from the >> perspective of reusing an already-loaded dll. > > Nope. Here's a test case: Sorry, I should have been more clear about the use case I was describing. I am specifically talking about multiple processes reusing a single copy of a dll that had been loaded into memory. > unpack, then > > (cd dlltest/lib && make) > (cd dlltest/app && make) > (cd dlltest/app && make test) If I understand your example correctly, when you run "make test," only a single process runs (your a.exe). >From my post: That is, if app1.exe is launched first, and uses c:\dir1\lib.dll (because of the various rules for searching for a dll), app2.exe is launched second, I was imagining having more than one process running (app1.exe, app2.exe, and app3.exe). > You'll get this output: > ... > This shows that app/cyga.dll is being loaded to satisfy lib/cygb.dll's > need for cyga.dll -- and NOT lib/cyga.dll. However, I do think I misunderstood John's use case, which I think does match your example. (I think I was misdirected by his phrasing "Windows first checks to see if the DLL is already loaded." This made me think of Windows loading the dll into physical memory.) > Chuck Thanks for your explanation and example. K. Frank |
From: Earnie <ea...@us...> - 2011-03-14 12:21:22
|
Paul Leder wrote: > On 11/03/2011 13:17, Earnie wrote: > >> An ugly workaround to the real problem is to put program A in a >> directory with its libstdc++-6.dll and put program B in another >> directory with its libstdc++-6.dll and then add the directories to PATH. > > This doesn't work, although I don't yet understand why. PATH itself > shouldn't be relevant here, as the app's installation directory should > come up earlier in the dll search order anyway. I'm hoping to find out > what's going on here tonight... > Maybe the base address is the same for both libraries and therefore has memory collision? As I understand Windows workings, if the dll is in the same directory as the binary then that dll would be used. But if both dll have the same entry point then there will be collision. >> Another workaround, and probably the better, use only one distribution >> of compiler. Why do you need to use both? > > Well, this is the real problem. I'm responsible for App 'foo'; App 'bar' > isn't mine, and I don't compile it. There may be hundreds (Ok, 3 or 4) > exes on my Windows box that I know nothing about, but which were build > with MinGW, each of which has its own libstdc++. It doesn't matter (does > it?) if some of them were compiled on mingw-w64, and some on mingw; what > matters is if they require different libstdc++ versions. > I agree that libstdc++ between the vendors needs a vendor stamp so that each vendor can distribute the shared library without conflict. However, I am not the one creating the packages. I don't know that we thought through that scenario. -- Earnie -- http://www.for-my-kids.com |
From: Charles W. <cwi...@us...> - 2011-03-14 13:57:38
|
On 3/14/2011 8:21 AM, Earnie wrote: >>> An ugly workaround to the real problem is to put program A in a >>> directory with its libstdc++-6.dll and put program B in another >>> directory with its libstdc++-6.dll and then add the directories to PATH. >> >> This doesn't work, although I don't yet understand why. PATH itself >> shouldn't be relevant here, as the app's installation directory should >> come up earlier in the dll search order anyway. I'm hoping to find out >> what's going on here tonight... >> > > Maybe the base address is the same for both libraries and therefore has > memory collision? As I understand Windows workings, if the dll is in > the same directory as the binary then that dll would be used. But if > both dll have the same entry point then there will be collision. No. IIRC DLL resolution is solely by name. If a process already has one version of libstdc++6.dll in memory, THAT copy will be used to resolve dependencies for all DLLs that have a dependency on "libstdc++6.dll" /in that process/. Different processes can have different libstdc++6.dll's, of course. This is why the mingw64 guys wanted to modify the naming convention for 64bit DLLs -- especially the gcc runtimes -- to make their names distinct from 32bit ones, but that was shot down by gcc AT gnu.org. -- Chuck |
From: K. F. <kfr...@gm...> - 2011-03-14 16:17:22
|
Hello John! On Mon, Mar 14, 2011 at 10:24 AM, John Brown <joh...@ho...> wrote: > > On Mon, 14 Mar 2011 08:21:09 -0400, Earnie wrote: > >> >> Maybe the base address is the same for both libraries and therefore has >> ... > My understanding is that Windows first checks to see if the DLL is > already loaded. If it is, then the .exe will use the loaded copy. > I could be wrong. It is described somewhere in the Windows Programmer's > Reference, but I'm lazy. I'm speaking from memory from many years ago, but my understanding is that different dll's with the same name -- that is, the same file name, but residing in different directories -- count as different dll's from the perspective of reusing an already-loaded dll. That is, if app1.exe is launched first, and uses c:\dir1\lib.dll (because of the various rules for searching for a dll), app2.exe is launched second, and would normally use c:\dir2\lib.dll, if launched in isolation, and app3.exe is launched third, and uses c:\dir1\lib.dll, then app2.exe will, in fact, load and use c:\dir2\lib.dll, even though a different copy of "lib.dll" (the one in c:\dir1) has already been loaded by app1.exe. app3.exe, however, will reuse the c:\dir1\lib.dll that was loaded by app1.exe. > Regards, > Alias John Brown. Best. K. Frank |