Windows C Runtime library not linking like I expect? - c

Being a long-time POSIX/Linux/BSD C developer and now trying to do a few things with Visual C++ 2010, I'm kind of fumbling around with the tooling because it doesn't quite work the same as the GCC toolset does. In theory, at least according to the docs, it seems very similar (and I'm sure it is), but I'm not seeing the things I'm expecting to see.
In this case, I'm trying to build a C library for later use in a .NET project, and I want to be careful to avoid runtime conflicts later on. My thought was to build a static library, linked against a DLL version of the C runtime (msvcr100d.dll in the Debug config) so I set the /MDd flag. However, when I use dumpbin.exe to inspect the resulting .lib output, it shows no dependents or imports.
Two questions, really:
Is this a bad idea in the first place? Should I be building a DLL or linking against the static CRT instead?
Why doesn't dumpbin.exe show the dependency on the CRT when I use /MDd?
Update: Choosing the Correct C/C++ Runtime Library is pretty helpful and informative. I tried the dumpbin incantation he suggests, and the output shows that the lib does link to msvcrtd as expected, but that doesn't really answer my second question above.

Because this is not a final EXE or DLL there is no import section. Instead, there are linker directives that say how this lib would like to be linked.
dumpbin /directives thoraway.lib
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file throwaway.lib
File Type: LIBRARY
Linker Directives
-----------------
/FAILIFMISMATCH:"_MSC_VER=1600"
/FAILIFMISMATCH:"_ITERATOR_DEBUG_LEVEL=2"
/DEFAULTLIB:"msvcprtd"
/DEFAULTLIB:"MSVCRTD"
/DEFAULTLIB:"OLDNAMES"
/EDITANDCONTINUE
Summary
CFC .debug$S
4C .debug$T
A2 .drectve
B .rdata
4 .rtc$IMZ
4 .rtc$TMZ
49 .text

Related

How do I read the source code for a C library in CLion

OS: Deepin 20 (base on Debian 10)
CLion: 2020.1.2
GCC: gcc (Uos 8.3.0.3-3+rebuild) 8.3.0
Make: 4.2.1 x86_64-pc-linux-gnu
Cmake: 3.18.1
I am a newcomer who just started learning C language. When I was writing C code using CLion, I could access it by Ctrl + mouse click .
I'm calling the method inside the header function. For example, if I use printf , I can access the stdio.h file, which can be seen at line 332 extern int printf (const char * ___, RESTRICT, format,...) ; .
But if I want to see the details of this method
I can't see it. According to Navigate in the code structure
Use Ctrl+Alt+Home to switch. But the IDE prompts No related file .
How can I get the source code to call a method? I want to learn from the good experiences of others by looking at their implementation logic in their libraries
Thank you for your review. I would really appreciate it if you could help me.
Even if most of GNU/Linux software is open source, it is not installed (in source code form) by default on your computer.
Regarding C programming, see Modern C (and the C11 standard n1570) and read the documentation of your C compiler (perhaps GCC or Clang, or simpler ones like nwcc or tinycc), your linker (probably binutils), your build automation tool (e.g. GNU make or ninja or cmake). Enable all warnings and DWARF debug info, so if using GCC compile with at least gcc -Wall -Wextra -g; then improve your C code to get no warnings. Once you have debugged your C source code (using GDB and perhaps valgrind), add optimization flags such as -O2. Order of arguments to gcc matters!
Consider, for some tasks, generating some of your C code (perhaps some #include-d header file) with tools like GNU bison, ANTLR, SWIG, RPCGEN, AWK, GUILE, GPP, GNU m4, GNU autoconf - or your own program or script.
I want to learn from the good experiences of others by looking at their implementation logic in their libraries
You need to fetch the source code from elsewhere.
For examples, see GNU libc or musl-libc, and the Linux kernel (and others: GTK, PostGreSQL, sqlite, GUILE, etc.... including many open source programs mentionned in this answer) and look also on websites like github, gitlab, sourceforge
Read also Advanced Linux Programming and syscalls(2). See also http://linuxfromscratch.org/
In 2020, a recent GCC compiler happens to handle specially calls to printf when asked to optimize. See the softwareheritage and Frama-C projects.
In some cases, consider accepting plugins in your program with dlopen(3) and dlsym(3) (see also elf(5) and How to Write Shared Libraries). You might even generate some code at runtime with libraries like libgccjit (or generate C code at runtime, then compile it as a plugin, and load it; such an approach is called metaprogramming and is related to partial evaluation; see also the blog of the late J.Pitrat for more insights).
Of course, you need tools to navigate in source code. Consider using GNU emacs combined with GNU grep for that, or some other source navigator. For large programs of millions of source code lines, consider writing your own GCC plugin to understand them.
Use also tools like strace(1) and GDB to understand the dynamic behavior of programs.
Expect several months of full time work to explore all this.
You could be interested by ACM conference papers also.
For your own source code, consider using some version control tool such as git. Of course read its documentation. And use LibreOffice, Lout or LaTeX, MarkDown (perhaps combined with inkscape or diagrams for figures) to write the documentation of your software.
In some cases, you might consider generating parts of the documentation from parts of your source code (e.g. using literate programming techniques like nuweb or documentation generators like doxygen).

Compile Fortran program with IFORT and using object files (i.e. .lib) compiled in Microsoft Visual Studio

I have a basic question that I cannot find the answer to even after searching the web many times.
Is it possible to compile a Fortran program by IFORT that uses (as dependencies) object files (i.e. .lib) that were compiled by Microsoft Visual Studio C?
Yes, it is possible, and is even rather easy. You have several options for how to do this:
Add the MSVC library project to your Fortran Visual Studio solution and then use Project > Dependencies to add the C project as a dependent of your Fortran project *does not work if the C project creates a DLL)
Add the .lib from the C project to the Fortran project as if it were a source file
Name the C .lib in the Linker > Input > Additional Dependencies project property.
I generally recommend the first choice, as it means you don't have to fuss with different settings for Debug and Release projects. You do need to make sure that the C library is built to specify the same run-time library type (Debug vs. Nondebug, DLL vs. Static) as the Fortran project. This is in the Code Generation property page for C.
There is a worked example "Fortran Calls C" in the Intel Parallel Studio XE for Windows Sample Bundle.
You'll also need to understand how to call a C procedure from Fortran and ensure that the C arguments have compatible Fortran types. It works best if you make use of the Fortran standard's "C interoperability" features.

What library has the __main function reference in gcc assembly output

When compiling an empty c program using MinGW the assembly output contains the line
call __main
what library is this from? I expected linking with msvcrt.dll to work (linking using ld), but as it did not, it must be define elsewhere.
There are many related/practically the same question elsewhere, but none of them (as far as I have seen, been searching for a while now) actually contain the answer to this question, so please double check before marking as duplicate.
__main should be provided by the libgcc library, which comes with the MinGW compiler.
If you use the compiler driver (that is, the gcc command-line tool) to link your program, rather than invoking ld directly, this library should be automatically added to the link. Using the compiler driver to link is recommended practice for this and several other reasons.
Depending on exactly which version of MinGW you have and which version of GCC it embeds, libgcc or part of it may be a DLL, which you must bundle if you are shipping MinGW-compiled executables.
On my Windows 10 machine, it is in \Program Files\mingw-w64\x86_64-8.1.0-win32-seh-rt_v6-rev0\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\libgcc.a which is then linked directly with the executable, so you do not have to include any DLL with you software.

Forcing name mangling in x64 DLL

I am porting a 32-bit application to 64-bit. The application supports plugins which are DLLs. Unfortunately, one of the mandatory functions each plugin needs to have is called FreeLibrary which of course conflicts with the kernel32 API of the same name. The reason why my plugin API uses the FreeLibrary name is that the application originated on a different platform where FreeLibrary doesn't clash with any OS APIs.
However, even on 32-bit Windows using FreeLibrary is not a problem because 32-bit DLLs use name mangling, i.e. the function is stored as _FreeLibrary and hence doesn't clash with the kernel32 API.
On 64-bit, though, I have a problem now because 64-bit doesn't seem to use name mangling. On 64-bit the compiler creates a symbol named FreeLibrary and this of course clashes with the kernel32 API of the same name and refuses to link, leading to the following error:
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
kernel32.lib(KERNEL32.dll) : error LNK2005: FreeLibrary already defined in test.o
Creating library test.lib and object test.exp
test.dll : fatal error LNK1169: one or more multiply defined symbols found
Thus, I'm wondering whether there is any way to force x64 DLLs to use name mangling as on 32-bit so that my DLL can export a symbol named FreeLibrary without any clashes with kernel32?
Or is there any other solution to work around this problem?
The only solution I see is to rename FreeLibrary to something that doesn't clash with OS APIs for the x64 versions of my application but of course I'd like to avoid this because it reduces the consistency of my application's plugin API. If possible, I'd like to keep the FreeLibrary name across all platforms and architectures.
Any ideas? I guess if it was possible on 32-bit to use reserved names like FreeLibrary in a DLL then there should be a way to do it on 64-bit as well, shouldn't there? But I don't see how...
I would not try to convince the compiler to mangle the names of the functions. That way lies madness.
To clarify, your only issue is the duplicate symbols when linking plugin DLLs. The application itself shouldn't care what the functions are named, because it's going to call the plugin entry points through function pointers received via GetProcAddress.
Assuming, the plugins don't ever need to call Windows APIs implemented in kernel32.dll, you could try omitting kernel32.dll from the linker command. (See the /NODEFAULTLIB option.) If kernel32.dll isn't part of the link, there should be no collision.
But that won't work because /MT in the command line implies you depend on the C run-time library, which, in turn, depends on some kernel32.dll APIs. (Also, are you sure you want to link the plugins against the static run-time library and not the DLL version?)
So the remaining option is to change the name of the function. This should be trivial, since you're porting anyway. You could even use the preprocessor to hack the name when compiling the plugins so that you don't need to change their source code:
cl /EHsc /c /DFreeLibrary=Plugin_FreeLibrary /Fotest.o test.c
And then change the GetProcAddress call in the application to look for Plugin_FreeLibrary instead of FreeLibrary, which I assume happens in just one place.

Static link intel CRT

I am compiling a C code using the intel compiler. I integrated icc with visual studio 2010. I want to generate an optimized executable which will run on a windows machine. It is actually a virtual machine in the cloud. I don't have a chance to install any redistributable library to the target machine. I want to statically link all the required libraries. How can I do this?
I suppose you meant icl since you're mentioning VS2010/Windows (icc would be Linux/Mac version): just selecting 'Multi-threaded (/MT)' under Project settings->Configuration properties->C/C++->Code Generation should work. It'll cause both MSVC and Intel runtime to be statically linked into app.
But then it also depends which other libraries are you using, it might not work for all. In that case you can check the dependencies with depends.exe (http://www.dependencywalker.com/) and copy them side-by-side with your .exe to target machine.
Try adding -i-static -static-libcxa to the final linkage.
This should force static linking for intel libraries only.
(You can also try -static as littleadv suggested in the comment, but this will produce a huge static executable with no shared libraries at all)
One more note: A simple workaround would be to copy the executable with the required shared libraries (those that do not exist at the host) to the same directory. Then set LD_LIBRARY_PATH=. before running your dynamically linked executable. This will force searching for libraries in the current directory as well as system directories.
EDIT: I just noticed you said "windows machine". The above is relevant to UNIX machines so probably not useful to you. I'll leave it here in case someone needs the information.

Resources