To begin with thank you guys for your work, and I hope my question has not been covered in a previous topic.
Here is my problem:
I built zlib with the mingw-w64-bin_x86_64-mingw_20100428_sezero toolkit without without issues, and I used the dll and lib produced to use it as a dependency in a visual studio project I want to use in a 64bit environment.
The link just goes fine, but I got a runtime error 0xc0000142 application failed to initialize properly.
If i replace the zlib dependency with a .lib and .dll generated by visual studio, everything goes fine.
Have you got any clue about what may be going wrong?
I can provide more details about the compiler linker settings. I just made a dummy vs project which reproduces that crash with just an .exe linking to a dll which depends on zlib "solely".
The *.dll should be portable, no need for this or that compiler-produced version, but how does gcc (ld) produce a *.lib file already?
Runtime mismatch problem?
gcc … -Wl,-output-implib…?
Jon: Are an *.dll.a from -out-implib and an M$ *.lib fully compatible to each other?
in the example of zlib, I got three libs produced a static lib called libz.a, a implementation lib called libzdll.a and a shared lib called zlib1.dll.
I just renamed libzdll.a into zlib.lib. Was that something stupid to do?
sezero: Mostly compatible to older versions of MSVC with its "long format" archive. The newer versions of MSVC (I think from 2005 onwards) have switched to producing "short" format archive. It still reads "long" format, but complains with some warning.
Sorry, I don't have more details on it.
fjourdes: renaming doesn't do anything unfortunately. msvc treats .lib as gcc treats .a files. Does your app crash immediately with 0xc0000142?
jon_y: yes it crashes immediately.
For what it is worth, i'll just add that I get a 0xc0000139 if I try to integrate the zlib I compiled with mingw-w64 as a dependency in a larger project which is compiled using visual studio.
In that case I got a runtime complain about some glut function entry point (the project used glut as a dependency as well, but I build this dependency with visual) that could not be found in zlib1.dll
Of course removing dependencies to zlib or replacing it by the x64 version compiled by visual studio solves the problem.
Does setting a breakpoint in main() through MSVC stops it from crashing immediately? If possible, do put up a minimalist testcase that causes zlib to fail.
jon_y: unfortunately it does crash immediately. I think I have turned on all possible debugging options.
]this project contains a visual studio 2008 solution file exposing the problem. It is a visual studio 2008 project, I just realized it may be inconvenient to test since it is a commercial version of visual studio.
If you prefer I can do it again with a msvc express version.
I guarantee you that you that unless you have the archive patches I have provided at http://github.com/tpaxatb/buildscripts/tree/master/binutils-patches you will not be able to successfully run gcc (actually binutils linked) runtime DLLs with MSVC linked programs
Try applying those patches (the implib and longname at least) and see if that works.
The issue is that the MS linker will *NOT* generate all the RVAs the .idata import sections if the archive member names are not the same across all linked objects for the same dll. Both patches are needed to get it working completely (if you are using dll names longer than 14(i think) chars).
There is a workaround: Ensure that you pass /OPT:NOREF /OPT:NOICF to the MS linker to prevent comdat folding and keep all references. You'll end up with a larger exe, but it will probably work.
can you use msvc to step through to the point in your code that causes the crash? Does it crash at gzopen/gzclose?
The code itself looks OK.
(note: come to think of it I'm not sure if the /OPT:NOICF is required, but I know that /OPT:NOREF is, so that the .idata sections aren't thrown out)
@jon_y: I could not manage to get anything from the visual studio debugger. I tried to make it catch the 0xc0000142 exception without success using a debug build of zlib. I am running out of idead today, I'll investigate more the matter tomorrow.
@tpaxatb: thank you for your input, I'll try this asap and keep you updated.
Sorry, I misread your earlier message. Can you use dependency walker on the gcc produced zlib dll? Does it use the libgcc dll?
@jon_y: dependency walker tells me that the zlib dll produced does not use libgcc dll
That's not the issue. If the linker is run with /VERBOSE for the failed run, I guarantee you will see a bunch of "removing unused __imp__ from .idata$5" You'll also see it (probably) dropping .idata$2, which contains the DLL name, and probably more.
Those are rather important, because that's what holds the RVAs that the main code jumps to. If you look at the assembly at runtime on the failed instruction, you'll probably see that you're jumping to some weird spot.
If you tell the linker to not remove unreferenced calls (/OPT:NOREF), the linker will keep the .idata sections, which will be located correctly at runtime.
(You can see this easily if you generate linker maps for both builds. The good build will have a bunch of extra __imp__* symbols in the .idata sections, along with keeping the lib__dllname. symbol. Those are all important for generating the correct relocation sections.
fjourdes: Can you please try this new toolchain: mingw-w64-bin_x86_64-mingw_20100505_sezero.7z. This one includes several patches from Doug Semler that is intended to provide import lib compatibility with m$. You will need to rebuild your zlib, etc from start using the new toolchain. (Note that this build is technically considered experimental and not tested by me, but I uploaded it in hope that it might help with your issue and the new patches would get tested.)
Thank you for your inputs, I have finally tested your suggestions this morning. I am sorry I did not have the time to do it before.
I am sorry I mislead you, I could not step into the code using the debugger simply because I was not building zlib using the good linker options. I was missing the -Wl,-output-implib. I am sorry I should have checked that right away, it is written clearly in the mingw faq that the dll produced without these flags won t work in any circumstances if you forgot to do that.
Eventually I edited the makefile, and I also realized later on that after release 1.2.3 zlib uses the -Wl,-output-implib linker flag to build the shared lib. So, finally, with all things compiled properly I get in visual studio a 0xC0000005 ( access violation) and yeah I can step into the code from there, so I could have given more info.
@tpaxatb: as you predicted, setting the /OPT:NOREF flag in the linker solves the runtime issue . The /OPT:NOICF is not mandatory.
@sezero: using your toolchain my simple zlib test project works fine, no need to specify the /OPT:NOREF option in the msvc linker.
Again thank you for all your answers. I am freshly graduated, and I gained a lot of knowledge on how linking works by reading your suggestions.
fjourdes: This is truly good news. I will upload a new toolchain soon in a few days wthout marking it experimental. There is still one glitch around about the __ImageBase linker symbol but Kai is already working on it. Thanks for the feedback!
Uploaded new toolchain sezero_20100513 with all the fixes integrated.
Log in to post a comment.