Can you handle compile time errors in c++? - c++

My project has a function that clears the terminal, which is implemented using the curses library. Compiling with the -lcurses flag works fine, but compiling without yeilds
/tmp/cc3T2MVI.o: In function `ClearScreen()':
clear_term.cpp:(.text+0xb): undefined reference to `cur_term'
clear_term.cpp:(.text+0x26): undefined reference to `setupterm'
clear_term.cpp:(.text+0x37): undefined reference to `tigetstr'
clear_term.cpp:(.text+0x3f): undefined reference to `putp'
collect2: ld returned 1 exit status
This is obviously expected because it cant find the library, but because this functionality is supplemental it would be preferable to define ClearScreen() as an empty function than to have compilation fail. I know that I put the function definition in a #ifdef block but I don't know any flags defined by curses.
Is it possible to catch these errors and instead define ClearScreen() as an empty function?

You can define a macro in the Makefile:
use_curses=1
FLAGS+=-DUSING_MAKEFILE
ifeq ($(use_curses),0)
FLAGS+=-DNO_NCURSES
else
LIBS+=-lcurses
endif
And in the code:
#ifndef USING_MAKEFILE
# error "Please use provided Makefile to compile!"
#endif
#ifdef NO_CURSES
void ClearScreen() { }
#endif

Actually, that is a linker error. And no, it can't really be caught at compile time. But one possibility would be to load the shared object dynamically in ClearScreen. If it failed to load the library, then it could just return. Doing the check at run time may be preferable to build time checks if you are not guaranteed to be building the binary on the target system on which it will ultimately be running.

You really need this library.
Maybe it will help you: http://linux.die.net/man/3/tigetstr

What you are trying to do (configuring the project with respect to dependencies) — is the classical task of build systems.
For example, with CMake, you'll have FindCurses module, which defines CURSES_FOUND preprocessor variable (if it founds the library).
With GNU Autotools you'll have similar macro, consult the relevant documentation.
If you're using your own build system — then you have to manually code the handling of relevant flags in configuration time.

Your build script should detect whether a suitable version of curses is present on the build machine. You can generate such script with GNU Autotools for example (the result iwould be a familiar configure script. You can also write a simple custom script insh/bash.

The problem you haven't considered is that your code probably #include's ncurses.h, which won't ever work without the library being installed where the compiler can find it.

Related

Atollic TrueSTUDIO: How to convert from C to C++?

I try to convert my project to C++ in TrueSTUDIO for STM32 by
Selecting project (in C/C++ Projects tab)
Right mouse button, select New/Other
In C/C++ tab, Convert to a C/C++ Project (Adds C/C++ Nature)
When pressing Next, nothing happens (unclear why)
When I press Next again, I see: Convert to a C/C++ project: The wizards adds C/C++ Nature to the selected projects to enable C/C++ Tools Supports for them
I press Finish
Than nothing happens, when I change main.c to main.cpp, I get the following error after build:
startup\startup_stm32f407xx.o: In function `LoopFillZerobss':
C:\Users\Michel\OneDrive\Stm32\Stm32CubeProjects\Fcb1010\Debug/..\startup/startup_stm32f407xx.s:115: undefined reference to `main'
collect2.exe: error: ld returned 1 exit status
It seems still C is used (also in the command line (first part):
arm-atollic-eabi-gcc -o Fcb1010.elf Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.o Drivers\STM ...
I would expect g++ to be used.
How to change my settings/procedure to be able to use C++ within TrueSTUDIO for a CubeMX generated project?
UPDATE
I removed Atollic TrueStudio, removed AC6 System Workbench, and reinstalled AC6 System Workbench. Now I can use C++ at AC6 System Workbench, even using STL.
I do not dare to install Atollic TrueStudio again, since it breaks the existing installation of AC6 SystemWorkbench, probably because they both use Eclipse. A pity, since I liked some features of TrueStudio, but C++ is more important to me. So for me, no TrueStudio anymore.
The error you mention
startup\startup_stm32f407xx.o: In function 'LoopFillZerobss':
C:\Users\Michel\OneDrive\Stm32\Stm32CubeProjects\Fcb1010\Debug/..\startup/startup_stm32f407xx.s:115: undefined reference to `main'
collect2.exe: error: ld returned 1 exit status
Is a linker problem, I suspect the library is looking for a c main function. A C++ compiler performs name mangling, so the symbol will no longer be main.
Try changing the signature of your main to extern "C" int main(void)
Please follow below steps:-
Better convert all the .c file to .cpp manually
Check each header file and change macro which is specific to C language
change the main function from C type to C++ (void main to int main()) also return a value from your main function.
If you are using a make file check if specific C dependencies are referred and change them.
Hope this will help.

Is it possible to symbolicate C++ code?

I have been running into trouble recently trying to symbolicate a crash log of an iOS app. For some reason the UUID of the dSYM was not indexed in Spotlight. After some manual search and a healthy dose of command line incantations, I managed to symbolicate partially the crash log.
At first I thought the dSYM might be incomplete or something like that, but then I realized that the method calls missing were the ones occurring in C++ code: this project is an Objective-C app that calls into C++ libraries (via Objective-C++) which call back to Objective-C code (again, via Objective-C++ code). The calls that I'm missing are, specifically, the ones that happen in C++ land.
So, my question is: is there some way that the symbolication process can resolve the function calls of C++ code? Which special options do I need to set, if any?
One useful program that comes with the apple sdk is atos (address to symbol). Basically, here's what you want to do:
atos -o myExecutable -arch armv7 0x(address here)
It should print out the name of the symbol at that address.
I'm not well versed in Objective-C, but I'd make sure that the C++ code is being compiled with symbols. Particularly, did you make sure to include -rdynamic and/or -g when compiling the C++ code?
try
dwarfdump --lookup=0xYOUR_ADRESS YOUR_DSYM_FILE
you will have to look up each adress manually ( or write a script to do this ) but if the symbols are ok ( your dSym file is bigger than say 20MB) this will do the job .

G++ does not compile my source code with -O0 but it does with -O2 -DNDEBUG, how can I solve it?

I am writing a firmware for an ARM microcontroller. I have built the cross-compiler without syscalls, actually my RTOS (ChibiOS) provides a simple syscalls implementation.
All my code is written in C excepting some parts where I only use C++ for linking with Eigen library (a C++ template library for linear algebra, it is only headers).
If I compile my source example code with -O2 -DNDEBUG (as far as I know with NDEBUG the code won't need assert()) everything compiles fine and the firmware works.
If I compile my source example code with -O0 I have the following:
Linking build/ch.elf
/home/noether/workspace/tool-chains/arm-none-eabi-4.6.2/lib/gcc/arm-none-eabi/4.6.2 /../../../../arm-none-eabi/lib/thumb/cortex-m4/libc.a(lib_a-abort.o): In function `abort':
/home/noether/workspace/tool-chains/summon-arm-toolchain/build/arm-none-eabi/thumb /cortex-m4/newlib/libc/stdlib/../../../../../../../gcc-4.6.2/newlib/libc/stdlib /abort.c:63: undefined reference to `_exit'
/home/noether/workspace/tool-chains/arm-none-eabi-4.6.2/lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/thumb/cortex-m4/libc.a(lib_a-signalr.o): In function `_kill_r':
/home/noether/workspace/tool-chains/summon-arm-toolchain/build/arm-none-eabi/thumb/cortex-m4/newlib/libc/reent/../../../../../../../gcc-4.6.2/newlib/libc/reent/signalr.c:61: undefined reference to `_kill'
/home/noether/workspace/tool-chains/arm-none-eabi-4.6.2/lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/thumb/cortex-m4/libc.a(lib_a-signalr.o): In function `_getpid_r':
/home/noether/workspace/tool-chains/summon-arm-toolchain/build/arm-none-eabi/thumb/cortex-m4/newlib/libc/reent/../../../../../../../gcc-4.6.2/newlib/libc/reent/signalr.c:96: undefined reference to `_getpid'
collect2: ld returned 1 exit status
make: *** [build/ch.elf] Error 1
It does not matter if I put -DNDEBUG, I have the same output.
I am using those flags as well, -fno-exceptions and fno-rtti.
If I do not use/link the Eigen library (the only C++ stuff), g++ compiles the source fine even with -O0.
Actually, I implemented a simple _kill _getpid and _exit functions, and the code compiles, but the code goes from 13KB to 130KB, and It crashes (maybe I haven't written well those functions).
What I want is to remove this stuff from my code (abort, etc) if I use -O0, as it is done (I guess) with -O2.
Thank you very much. Let me know if you need more information.
These references are almost certainly due to using assert(); that will call abort() on failure, which in turn will try to raise a signal (using the kill() syscall in this implementation) to abort the process. Obviously, this isn't possible if you can't make syscalls.
Building with -DNDEBUG (like you do in the optimised version) will fix this; it causes the assert() macro to generate no code, so there will be no references to abort(). The optimisation level itself shouldn't make any difference.
Alternatively, if you want to preserve your assertions, you could implement your own assert() macro that doesn't require any syscalls.
You could simply implement stubs for those missing syscalls and link them to your code. That will keep the linker quiet, but you might make the stubs do something sensible or useful. exit() might disable interrupts and loop indefinitely or force a reset. _kill() might hook into your RTOS to terminate a thread, or simply call _exit(), and _getpid() might return some dummy value or an RTOS thread ID.

"undefined reference to" many (all?) of the functions in shared library (newbie)

I'm a novice at C++. Be patient if this is incoherent. I'm called upon to build a large system on linux that was originally built on OS X, where it works fine. The original authors are no longer with the company. The build system makes use of autotools, but there are also some hand made Makefiles which walk through the system calling the auto-made Makefiles. I've managed to get all of the c++ code compiled. The build system also uses libtools, and shared libraries are produced and deposited in /usr/local/lib.
So now I'd like to use these libraries. I've written a short program that simply instantiates an object of class ds_dictionary and calls one of its methods. Here it is:
#include <iostream>
#include <DSUtils/DSUtils.h>
int main (int argc, char * const argv[]) {
int32_t integer_data=123;
char key_alice_integer[] = "alice_integer";
ds_dictionary my_dict;
my_dict.add_int(key_alice_integer, integer_data);
return 0;
}
I compile this with
g++ -lDSUtils -o main my_test_code.cpp
With the result:
//usr/local/lib/libDSUtils.so: undefined reference to `ds_breakdown_from_time_interval'
//usr/local/lib/libDSUtils.so: undefined reference to `ds_date_breakdown_with_string'
//usr/local/lib/libDSUtils.so: undefined reference to `ds_seconds_duration_of_interval'
... (about 25 lines like these)
collect2: ld returned 1 exit status
Let's look inside the library:
garyp#VM:/usr/local/lib$ nm libDSUtils.so | grep ds_breakdown_from_time
U ds_breakdown_from_time_interval
The "U" in the line above ... does that mean that the library wasn't built correctly?
Am I calling g++ correctly?
Do I have to put something in the code to tell it that I'm using functions found in that library?
What are possible errors? Where should I start poking around?
EDIT:
Aha. The library DSUtils is built from several c++ sources. There is one c program in the source, and it contains all of the problem functions. The Makefile system doesn't deal at all with that one c file. That c program compiles. Ideally I suppose I'd figure out how to modify the Makefile to compile that file and add it to the library, but I'm not to the point where I can figure out how to do that.
Can I add the .o file to the existing library? How? Create a library with one file? etc?
EDIT_2: I simply did
g++ -o main -lDSUtils main.o my_new_objectfile.o
and the thing compiles, links, and runs without error. Should that work? After fixing a logic bug, it does work.
This
U ds_breakdown_from_time_interval
tells me that ds_breakdown_from_time_interval will be resolved by another library during runtime. So I am guessing you need to link to the library that defines ds_breakdown_from_time_interval.

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.