atexit() undefined with freestanding CLang - c++

I'm trying to compile and link some C++ code using CLang, with the following command line:
clang.exe -nostdinc -MD -fno-use-cxa-atexit -fno-rtti -fno-exceptions -fsigned-char -fno-stack-protector -fPIC -m64 -Wall -Werror -Wno-unused-function -Wno-unused-label -Wno-ignored-attributes
(I left out the output, includes, defines, etc. These are fine)
The issue I'm having is that during linking, I get the error
error: L0039: reference to undefined symbol `atexit'
I've spent quite some time on this issue already, but can't for the life of me seem to figure out how to properly resolve this.
My research so far has shown that atexit is defined in stdlib.h, but I can not use the standard library in this situation (this isn't my decision either, and is completely mandatory for this particular project).
As far as I can tell this issue is only now arising due to the fact that we now suddenly have static objects in our code which is compiled this way, which leads the compiler trying to register con/destructors to be executed for these objects, which requires a call to __cxa_atexit (which we've disabled because it was also giving undefined reference errors because of the same reason) or atexit.
I've also tried defining an arbitrary atexit function in my code, but apparently the linker doesn't want to have anything to do with this (which does seem rather strange to me).
So the question I have is: How can I get the linker to not whine about atexit, while not having to include the standard library?
Thanks a bunch in advance!

For future visitors, user damvac was able to help out!
Here's my comment about the issue being resolved:
It seems I forgot to add extern "C" to the definition of atexit (I only added it to the declaration), this seems to have resolved the issue! Thanks everyone who replied, and thank you davmac for providing the solution!

atexit (and the whole concept of "exiting" in general) do not exist in a freestanding environment, so you can't call it in your code.
To get the compiler to not generate support code that calls it, you need to compile all your source files with -ffreestanding to specify that you are using/generating freestanding code.

Related

Linker errors when optimization greater than -O1 (clang++)

I have a moderately large C++ / ObjC++ project in XCode, which compiles/links/runs just fine at -O0 (in Debug config), as well as with -O1, but anywhere above -O1 I get two very strange linker errors:
"std::__1::vector<BufferBinding, std::__1::allocator<BufferBinding> >::~vector()", referenced from: ... LevelSystem.o
"std::__1::vector<TextureHandle, std::__1::allocator<TextureHandle> >::~vector()", referenced from: ... LevelSystem.o
Oddly, vector<BufferBinding> and vector<TextureHandle> are used in many places in different object files, but I am only getting linker errors for my 'LevelSystem.cpp'. FWIW, LevelSystem.o is included via a separately compiled static library...
Unfortunately I have not been able to come up with a small code snippet to reproduce this problem, so rather then expecting a concrete solution I was just hoping for any advice for possible places to look or steps to debug further.
Compiling with
clang++ -x objective-c++ -arch arm64 -std=c++1y -stdlib=libc++ -fobjc-arc -O2 (...)
I know this is very little to go on, but Im just posting here in case anyone has experienced this kind of thing in the past and can point me in the right direction.
Thanks!
EDIT:
TextureHandle is a pimpl-y class, so really contains nothing more then a pointer to a forward-declared struct.
BufferBinding contains only an id<MTLBuffer> (and a few ints) which is ARCed, which is suspicious, but then again TextureHandle exhibits the same problem without having any ObjC pointers...

How to mark a *standard library* function/method as deprecated (or disabled altogether) in my project?

I'm trying to somehow disable/mark as deprecated the hideous std::string::operator=(char) overload (which in my experience is used only when mistakingly assigning an integer to a string, and causes subtle and difficult to track bugs).
I tried with:
an explicit specialization with a static assert in it
#include <string>
#include <type_traits>
template<> std::basic_string<char> &std::basic_string<char>::operator=(char c) {
static_assert(false, "Don't use this!");
}
which fails as <string> already does an explicit instantiation of std::string
the [[deprecated]] attribute, applied to a similar declaration as above in various positions; no position I tried seemed to yield any reasonable result;
=delete, which fails for reasons similar to above;
I thought about using linker tricks (in a similar vein, in the same project we have runtime checks on stray setlocale usages using the --wrap ld linker option), but the fact that this is a template and inline method complicates the matter.
Now to the questions:
is there a standard method to somehow disable (as would happen with =delete) any function or method in the standard library (read: in a library where you cannot alter the declarations in the headers)?
as above, but, instead of disable, add a warning (as would happen with [[deprecated]]);
failing the standard method, is there something g++-specific?
if there's no "general" (=applicable to any method, any class, any function, ...) solution, is there something that we could apply to this specific case (=disable a method of a template class, possibly even just a specific instantiation)?
You can use the following compiler/linker option:
$ g++ -O0 test.cpp -Wl,--wrap=_ZNSsaSEc
Explanation:
The _ZNSsaSEc is the decorated name of your offending function:
$ echo _ZNSsaSEc | c++filt
std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(char)
The -Wl compiler option is to pass options to the linker.
And the --wrap=<symbol> linker option transforms any reference to the given symbol to the alternative __wrap_<symbol>. And since you are (hopefully) not defining a function named __wrap__ZNSsaSEc, you will get a nice linker error:
test.cpp:(.text+0x26): undefined reference to `__wrap__ZNSsaSEc'
And -O0 is to disable optimizations and prevent the compiler from inlining the function. The linker trick will not work if there is inlining, as #SergeBallesta pointed out in the comment.
Maybe a bit of a hack, but hey, it works!
Well, I'm afraid that the standard library is intended to be... standard, and as such does not provide hooks to allow developpers to tweak it.
An ugly way (never say I advise you do use it ;-) ) would be to use the fact that Standard Library headers are just text files, so you can easily change them in you local developpement environment. A possibly less bad way, would be to setup a folder containing links to original headers except for the modified header and instruct compiler to use that folder for system headers.
That way, you can change anything you want, but... portability and maintainability... It's really a desperado solution...
This is clang++ specific, since I don't know what the equivalent functionality is called in the gnu toolchain. It's also somewhat overkill.
Rodrigo's suggestion of using the linker to swap out the symbol is great for non-inlined cases. If you build everything at O0 occasionally that'll suffice.
Otherwise, the llvm (clang) toolchain offers surprising amounts of control over the optimisation pipeline. For example, you can compile without optimisations, then run the optimisations yourself using opt, then convert to an object file.
clang++ -c test.cpp -O0 --emit-llvm test.ll
opt -O3 test.bc -o faster.ll
clang++ -c faster.bc -o test.o
The opt tool is extensible. I can't honestly say it's trivial to extend, but the process is well documented. You can write a compiler pass that warns when your standard library function is seen. The end result could be invoked something like:
clang++ -c test.cpp -O0 --emit-llvm test.ll
opt --load DeprecationPass.so test.bc -o /dev/null
opt -O3 test.bc -o faster.ll
clang++ -c faster.bc -o test.o
If you're confident the custom pass is correct (not merely useful) you can use a single invocation of opt. It's probably possible to pass flags through to opt via the clang front end, but it's not immediately obvious how to.
Overall, following rodrigo's suggestion and occasionally building the entire product at O0 is probably a better plan - but it is exciting that clang lets you do things like this.

Undefined reference to operator new

I'm trying to build a simple unit test executable, using cpputest. I've built the cpputest framework into a static library, and am now trying to link that into an executable. However, I'm tied into a fairly complicated Makefile setup, because of the related code.
This is my command line:
/usr/bin/qcc -V4.2.4,gcc_ntoarmle_acpp-ne -lang-c++ -O2 -g -g -o Application/UnitTests/Tests/symbols/UnitTestExe -Wl,--start-group Application/UnitTests/Tests/../.objs/main.o Application/UnitTests/lib/libcpputest.a -Wl,--end-group -lm
I'm getting many errors like the following:
Application/UnitTests/lib/libcpputest.a(CommandLineTestRunner.o): In function `CommandLineTestRunner::parseArguments(TestPlugin*)':
Application/UnitTests/cpputest/src/CppUTest/.objs/../CommandLineTestRunner.cpp:114: undefined reference to `operator new(unsigned int, char const*, int)'
I can't figure out what's causing this. Don't I get operator new for free with C++?
You probably need to link with the C++ support runtime library. This happens automatically when you invoke g++. On Linux, this is achieved by adding the -lstdc++ flag to the linker. You have to figure out how to do the same on your platform.
Maybe you're calling gcc, the C compiler instead of g++, which is the C++ compiler.
There's very little information in your question to work from, but it looks like some code uses some form of placement new, and while that special operator new is declared (the compiler finds it and compiles the code using it), the linker can't find its definition.
(Since this old answer of mine seems to still get attention: See here for an extensive discussion on declaration vs. definition.)
You need to rebuild your code from scratch, including the library. I got this error because I inadvertently copied object files compiled on another machine (with the rest of the source) to my machine. Most likely this disturbs the linking step since there are now two types of object files, native (for modified source files) and non-native (all others). I am guessing here, but the operator 'new' means slightly different things on different architectures and that's why you are getting this error.
p.s. I know this is way too late for a useful answer but I'm still posting this for the record.
For QNX 6.5.0 I have specified flag -lang-c++ for qcc (gcc) to avoid the error.
Like the original post, in my case this error happened while trying to link a software using CppUTest framework.
In my case, the source of the problem seems to be related to the fact I disabled the MEMORY_LEAK_DETECTION compile option of CppUTest. I enabled it again, which solved the problem.
Sometimes adding -lstdc++ is not enough. You should add it to the right place. For example I had list like this, not working:
target_link_libraries(cfr2 pthread m stdc++ "${CMAKE_SOURCE_DIR}/compressor/libcompressor.a" )
But this one works fine:
target_link_libraries(cfr2 pthread m "${CMAKE_SOURCE_DIR}/compressor/libcompressor.a" stdc++)
It'd be great if someone explained it in the comment section.

How can I find the calling routine for a symbol in case of a linker error "undefined reference"?

I have a problem linking an application for an embedded target. I'm developing on a windows box using Min-GW for an ARM9 target that runs under Linux.
Actually I'm switching from static linking to dynamic linking with .so-libraries to save memory space.
I get the error message
libT3Printer.so: undefined reference to `__ASSERT'
I checked all the sources for the lib and I have no idea where this function could be called. Is there any possibility to find out, who (which source file or function) could be the caller of the missing function?
The reference is probably being hidden by a macro. If you run the compiler with the -E option to generate predecessor output you might have a better chance of tracking it down.
Try to add definition NDEBUG.
In C, compiling with NDEBUG defined:
gcc -DNDEBUG foo.c
disables all calls to assert(), and this behavior is identical in C++:
g++ -DNDEBUG foo.cpp

Suppressing Linking Errors in G++ 3.4.6

Don't ask why, but is there any way to suppress a failed linking error?
Such as:
undefined reference to BLANK
This is in GCC 3.4.6
No, because they are errors and not warnings. By definition this means that the function was referenced someplace but not defined... that's not something you can just ignore.
The only way of supressing the link errors would be not linking (or not having errors in the first place). As mentioned by SoapBox, errors cannot be silently ignored.
If you post some code you could get to a solution to the problem that is better than trying to close your eyes and wait for the problem to go away (they don't usually).
It's not the compiler, but the linker. The best way to "suppress" this would be to pass in the library name with the compile command:
gcc try.cc -lstdc++
or
g++ try.cc -lfltk
for instance.