I'm getting a strange exception when using Cocoa together with a personal C++ library, while the exception only occurs in debug mode - in release mode everything is fine. And to stress that, it suffices to link my C++ library to get the exception, I don't need to call my library at all.
The error I get is "Exception: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)".
The C++ library is built using CMake and the mode is determined by the internal "CMAKE_BUILD_TYPE". The library can be found on GitHub, though I don't think that anyone wants to build it. Also because it is quite huge, I don't think that someone wants to look at the code.
A very minimal example to demonstrate the error is the following one:
#include <Cocoa/Cocoa.h>
int main()
{
[NSApplication sharedApplication];
printf("success\n");
return 0;
}
As you can see, this example does not use my lib at all.
Compiling it with "clang main.mm -framework Cocoa" works just fine
Compiling it with "clang main.mm -framework Cocoa -lmylib" works also. "mylib" is built here with "-DCMAKE_BUILD_TYPE=Release"
Compiling it with "clang main.mm -framework Cocoa -lmylib_d" yields the above exception. "lmylib_d" is built here with "DCMAKE_BUILD_TYPE=Debug". It prints: "Segmentation fault: 11".
I don't understand it. What could I possible have done in my library that crashes Cocoa just because I link to it? The only thing that could come to my mind is that I have defined my own global operator new and delete. Still, Cocoa wouldn't use those, right?
Here is the full stack trace:
(anonymous namespace)::get_registry() (.8898) 0x00007fff564afd79
SLSNewConnection 0x00007fff56473dc4
SLSMainConnectionID 0x00007fff56474a87
_CFAppSleepSetupCoreGraphics 0x00007fff34649091
____CFRunLoopSetOptionsReason_block_invoke_2 0x00007fff34648738
_dispatch_client_callout 0x00007fff5c43ddb8
dispatch_once_f 0x00007fff5c43dd6b
__CFRunLoopSetOptionsReason 0x00007fff34646ff3
_LSApplicationCheckIn 0x00007fff35ae7abb
_RegisterApplication 0x00007fff32ec192c
GetCurrentProcess 0x00007fff32ec064c
MenuBarInstance::GetAggregateUIMode(unsigned int*, unsigned int*) 0x00007fff3391e4ab
MenuBarInstance::IsVisible() 0x00007fff3391e435
_NSInitializeAppContext 0x00007fff31bc1197
-[NSApplication init] 0x00007fff31bc0590
+[NSApplication sharedApplication] 0x00007fff31bc01e6
main main.mm:5
start 0x00007fff5c477015
start 0x00007fff5c477015
Thanks for any help in advance!
Does your library have any static initializers? Or, link to other libs that do? Those are run before main is called, and if they could be causing issues. Especially if they try to interact with Foundation/AppKit.
Regardless, I'm fairly sure it is not safe to use NSApplication this way. I believe you must access it within the context of a main thread which calls NSApplicationMain to setup the underlying AppKit machinery. Since you are crashing within that machinery, I think that is the underlying issue.
Indeed #Kai Guther was correct. Cocoa was using my overridden global new. Apparently I had a bug in my replaced new operator. After a bit of refactoring of that function, it works now.
Thanks for the important information... I think without that guess I would've searched for ages for that terrible bug...
Related
I am building a shared library which uses Boost.thread internally. As a result, Boost.system is also used since Boost.thread depends on that. My shared library exports a C interface, so I want to hide all my internal exception handling and thread usage etc from the end user. It is supposed to be a black box so to speak. However, when I link with a client application, while the program runs fine - as soon as it is time to stop the processing by invoking a library function I get:
terminate called after throwing an instance of 'boost::thread_interrupted'
I catch this exception internally in the library, so I have no idea why it is not actually being caught. The end user's program is not meant to know about or handle Boost exceptions in any way. When building the shared library, I use static linking for both Boost.thread and Boost.system so the outside world is never meant to see them. I am on GCC 4.7 on Ubuntu 12. On Windows, I have no such problems (neither with MSVC or MinGw).
(EDIT)
I am editing the question to show a minimalistic example that reproduces the problem, as per the requests in the comments.
Here first is the code for testlib.cpp and testlib.h.
testlib.cpp:
#include <boost/thread/thread.hpp>
void thread_func()
{
while(1)
{
boost::this_thread::interruption_point();
}
}
void do_processing()
{
// Start a thread that will execute the function above.
boost::thread worker(thread_func);
// We assume the thread started properly for the purposes of this example.
// Now let's interrupt the thread.
worker.interrupt();
// And now let's wait for it to finish.
worker.join();
}
And now testlib.h:
#ifndef TESTLIB_H
#define TESTLIB_H
void do_processing();
#endif
I build this into a shared library with the following command:
g++ -static-libgcc -static -s -DNDEBUG -I /usr/boost_1_54_0 -L /usr/boost_1_54_0/stage/lib -Wall -shared -fPIC -o libtestlib.so testlib.cpp -lboost_thread -lboost_system -lpthread -O3
Then, I have the code for a trivial client program which looks as follows:
#include "testlib.h"
#include <cstdio>
int main()
{
do_processing();
printf("Execution completed properly.\n");
return 0;
}
I build the client as follows:
g++ -DNDEBUG -I /usr/boost_1_54_0 -L ./ -Wall -o client client.cpp -ltestlib -O3
When I run the client, I get:
terminate called after throwing an instance of 'boost::thread_interrupted'
Aborted (core dumped)
I am not explicitly catching the thread interruption exception, but according to the Boost documentation Boost.thread does that and terminates the given thread only. I tried explicitly catching the exception from within the thread_func function, but that made no difference.
(End OF EDIT)
(EDIT 2)
It is worth noting that even with -fexceptions turned on, the problem still persists. Also, I tried to throw and catch an exception that is defined in the same translation unit as the code that catches and throws it, with no improvement. In short, all exceptions appear to remain uncaught in the shared library even though I definitely have catch handlers for them. When I compile the client file and the testlib file as part of a single program, that is to say without making testlib into a shared library, everything works as expected.
(End OF EDIT 2)
Any tips?
I finally figured it out. The -static flag should never be specified when -shared is specified. My belief was that it merely told the linker to prefer static versions of libraries that it links, but instead it makes the generated dynamic library unsuitable for dynamic linking which is a bit ironic. But there it is. Removing -static solved all my problems, and I am able to link Boost statically just fine inside my dynamic library which handles exceptions perfectly.
Maybe this?
If you have a library L which throws E, then both L and the
application A MUST be linked against X, the library containing the
definition of E.
Try to link executable against boost, too.
A shared library that itself includes statically linked libraries is not such a good idea, and I don't think that this scenario is well supported in the GNU toolchain.
I think that your particular problem arises from the option -static-libgcc, but I've been unable to compile it in my machine with your options. Not that linking statically-dinamically to libpthread.so sounds as such a good idea either... What will happen if the main executable wants to create its own threads? Will it be compiled with -pthread? If it is, then you will link twice the thread functions; if it isn't, it will have the functions but not the precompiler macros nor the thread-safe library functions.
My advice is simply not to compile your library statically, that's just not the Linux way.
Actually that should not be a real problem, even if you don't want to rely on the distribution version of boost: compile your program against the shared boost libraries and deploy all these files (libboost_thread.so.1.54.0, libboost_system.so.1.54.0 and libtestlib.so) to the same directory. Then run your program with LD_LIBRARY_PATH=<path-to-so-files>. Since the client is not intended to use boost directly, it doesn't need the boost headers, nor link them in the compiler command. You still have your black box, but now it is formed by 3 *so files, instead of just 1.
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 .
I have a system for building my software already set up, using a makefile and command-line tools.
I have been easily able to modify the makefile to support my Mac (10.7.4 now), so I am trying to get my code to work independently of XCode. I'll deal with XCode once I start porting stuff to iOS. My hope is that a makefile solution (while my codebase is still manageable by said makefile) allows me better options for portability and automation.
I am experiencing exactly what is described here. The code compiles and problems are encountered on run-time.
At first I was using the SDL framework (-framework SDL) from the binary download on the SDL site, so I figured I could fix the problem by properly building SDL from source. I have done this and am now linking to libSDL.a and libSDLMain.a. This in turn requires me to include these additional frameworks to successfully compile (I came up with the list based on the output of sdl-config --static-libs:
-framework Cocoa -framework IOKit -framework AudioToolbox -framework AudioUnit -framework Carbon -framework ApplicationServices
However I still have the same problem, which the article explains has to do with missing this:
[NSApplication sharedApplication];
My code has no Obj-C code. I'm happy to plug some Obj-C into it, though. I added SDLMain.m that came with one of the packages but the linker has a problem with that: ld: duplicate symbol _main
Okay, so I'm not gonna get away with that so easy.
What's the little piece I'm missing that will let me initialize my NSApplication? Is there a way to do it without having a separate source file (from my Main.cpp) which must now be Obj-C? Is there some C/C++ wrapper function that I can call sharedApplication with?
If you link with libSDLmain, or include SDLMain.m, your entry point will have to be named SDL_main instead:
extern "C" int SDL_main(int argc, char **argv)
{
}
(The extern "C" takes into account the fact that you are using C++.)
The "real" main, included in libSDLmain or SDLMain.m, makes the necessary Mac-specific preparations and then calls SDL_main.
There is a pure C solution to this as well: doing the compiler's work in lowering the Objective-C call to a C call, or a set of C calls.
#include <objc/runtime.h>
#include <objc/message.h>
static void createSharedApplication(void)
{
id myNSApplication = objc_getClass("NSApplication");
SEL mySharedApplication = sel_registerName("sharedApplication");
id (*myMsgSend)(id, SEL) = (id (*)(id, SEL))objc_msgSend;
myMsgSend(myNSApplication, mySharedApplication);
}
As you can see, however, this is not very elegant.
A lot of credit should go to RavuAlHemio because he pointed out for me enough information about what SDL is doing (trying to do) with the entry point. I then edited my code slightly, from
#undef main
int main(int argc,char *argv[]) {
to
int main(int argc,char *argv[]) {
The only reason I had it the first way was because on Windows via MinGW (but not Linux) stdout and stderr were redirected to files rather than put on the terminal. I will now have to come up with a more elegant solution for that.
Anyway, this has solved the problem.
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.
I am trying to port a fairly large C++ project to using g++ 4.0 on Mac OS X. My project compiles without errors, but I can't get GDB to work properly. When I look at the stack by typing "bt" on the GDB command line, all file names and line numbers displayed are wrong.
For example, according to the GDB stack trace, my main() function is supposed to be in stdexcept from the Mac OS X SDK, which does not make any sense.
What could cause GDB to malfunction so badly? I've already checked for #line and #file statements in my code and made sure that the code only has unix line endings. I've also cleaned and rebuilt the project. I've also tried debugging a Hello World project and that one did not have the same problem.
Could the problem have to do with one of the third party libraries I am linking and the way those are compiled? Or is it something completely different?
Here are two exemplary calls to gcc and ld as executed by Xcode. AFAIK all cpp-files in my project are compiled and linked with the same parameters.
/Developer/usr/bin/gcc-4.0 -x c++
-arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -fpermissive -Wreturn-type -Wunused-variable -DNO_BASS_SOUND -D_DEBUG -DXCODE -D__WXMAC__ -isysroot /Developer/SDKs/MacOSX10.5.sdk
-mfix-and-continue -fvisibility-inlines-hidden -mmacosx-version-min=10.4 -gdwarf-2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -D__WXDEBUG__ -D__WXMAC__ -c "/Users/adriangrigore/Documents/Gemsweeper
Mac/TSDLGameBase.cpp" -o
"/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Gemsweeper
Mac.build/Debug/Gemsweeper
Mac.build/Objects-normal/i386/TSDLGameBase.o"
/Developer/usr/bin/g++-4.0 -arch i386
-isysroot /Developer/SDKs/MacOSX10.5.sdk
"-L/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Debug"
-L/Developer/SDKs/MacOSX10.5.sdk/usr/local/lib
-L/opt/local/lib "-F/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Debug"
-F/Users/adriangrigore/Library/Frameworks
-F/Developer/SDKs/MacOSX10.5.sdk/Library/Frameworks
-filelist "/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Gemsweeper
Mac.build/Debug/Gemsweeper
Mac.build/Objects-normal/i386/Gemsweeper
Mac.LinkFileList"
-mmacosx-version-min=10.4 /opt/local/lib/libboost_program_options-mt.a
/opt/local/lib/libboost_filesystem-mt.a
/opt/local/lib/libboost_serialization-mt.a
/opt/local/lib/libboost_system-mt.a
/opt/local/lib/libboost_thread-mt.a
"/Users/adriangrigore/Documents/Gemsweeper
Mac/3rd
party/FreeImage/Dist/libfreeimage.a"
"/Users/adriangrigore/Documents/Gemsweeper
Mac/3rd
party/cpuinfo-1.0/libcpuinfo.a"
-L/usr/local/lib -framework IOKit -framework Carbon -framework Cocoa -framework System -framework QuickTime -framework OpenGL -framework AGL -lwx_macd_richtext-2.8 -lwx_macd_aui-2.8 -lwx_macd_xrc-2.8 -lwx_macd_qa-2.8 -lwx_macd_html-2.8 -lwx_macd_adv-2.8 -lwx_macd_core-2.8 -lwx_base_carbond_xml-2.8 -lwx_base_carbond_net-2.8 -lwx_base_carbond-2.8 -framework SDL -framework Cocoa -o "/Users/adriangrigore/Documents/Gemsweeper
Mac/build/Debug/Gemsweeper
Mac.app/Contents/MacOS/Gemsweeper Mac"
Please note that I have already asked a similar question regarding the Xcode debugger here, but I am reposting since I just learned that this is in fact not Xcode's fault, but a problem with GCC / ld / GDB.
Edit: My project makes use of the following third-party libraries: SDL, Boost, wxWidgets. I am not sure if this matters for this problem, but I just wanted to mention it just in case it does.
I've tried compiling an Xcode SDL project template and did not experience the same problem, so it must be due to something special in my project.
Second Edit: As I just found out, I made a mistake while searching files with the string "This is an automatically generated". I just found several dozen files with the same string, all belonging to FreeImage, one of the third party libraries I am using. So, the problem seems to be related to FreeImage, but I am not still not sure how to proceed.
I got those symptoms, when my gdb version didn't match my g++ version.
Try to get the newest gdb.
Your cpp files certainly have debug symbols in them (the -gdwarf-2 option).
Do you use a separate dSYM file for the debug symbols? Or are they inside the object files. I would first try to use DWARF in dSYM files and see if that helps (or vice versa)
The third party libraries appear to be release builds though (unless you renamed them yourself of course) e.g. I know for sure boost uses the -d monniker in the library names to denote debug libraries (e.g. libboost_filesystem-mt-d.a).
Now, this shouldn't really pose a problem, it should just mean you can't step into the calls made to third party libraries. (at least not make any sense of it when you do ;) But since you have problems, it might be worth a try to link with debug versions of those libraries...
Are you compiling with optimization on? I've found that O2 or higher messes with the symbols quite a bit, making gdb and core files pretty much useless.
Also, be sure you are compiling with the -g option.
Can it be that you are using SDL? SDL redefines main so your main will be named SDL_main and that the SDL parts might be heavy optimized so down there you'll have problem getting good gdb output.
...just a thought
Read this
For a test, you could check if addr2line gives you expected values. If so, this would indicate that there's nothing wrong with the ELF generated by your compile/link parameters and casts all suspicion on GDB. If not, then suspicion is still on both the tools and the ELF file.
I've tried compiling an XCode SDL
project template and did not
experience the same problem, so it
must be due to something special in my
project.
Correct. Your project settings are the thing that is different.
You will need to disable the debug optimizations in the Xcode project settings for the debug build. Xcode unfortunately makes GDB jump to weird lines (out of order) when you would expect it to move sequentially.
Go to your project settings. Set the following
1) Instruction Scheduling = None
2) Optimization Level = None [-O0]
3) ZERO_LINK = None
Your problems should go after after doing this.
Here is the project settings screen that you need to change the settings on:
From your flags the debug information should be in the object files.
Does your project settings build the executable in one location then move the final executable to another location when completed? If this is the case then gdb may not be finding the objectects files and thus not correctly retrieving the debug information from the object files.
Just a guess.
I encountered this several years ago when transitioning from the Codewarrior compilers to Xcode. I believe the way to get around this is to put the flag "-fno-inline-functions" in Other C Flags (for Dev only).
This problem was more pronounced on the PowerPC architecture for us.
What about if you remove the "-fvisibility-inlines-hidden" and "-mfix-and-continue" flags?
I've never had the "fix and continue" feature work properly for me.
WxWidgets do also define their own main if you use their IMPLEMENT_APP() macro
From here
As in all programs there must be a "main" function. Under wxWidgets main is implemented using this macro, which creates an application instance and starts the program.
IMPLEMENT_APP(MyApp)
See my answer here
I have now downloaded and compiled the FreeImage sources and yes, the file b44ExpLogTable.cpp is compiled into libfreeimage.a. The problem looks like the script gensrclist.sh just collects all .cpp files without skipping the one with a main in. That script generates a file named Makefile.srcs but one is already supplied. (running it on my Leopard failed, some problem with sh - it worked if I changed sh to bash)
Before you have changed anything this gives an a.out
c++ libfreeimage.a
The file Makefile.srcs has already been created so you should be able to remove the file b44ExpLogTable.cpp from it. Then do
make -f Makefile.osx clean
make -f Makefile.osx
When this is done the above c++ libfreeimage.a should give the following error
Undefined symbols:
"_main", referenced from:
start in crt1.10.5.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
I have a new thing you can try.
Just before your own main you can write
#ifdef main
# error main is defined
#endif
int main(int argc, char *argv[]) {
this should give an error if you have some header that redefines main.
If you define an own you might get an warning where a previous definition was made
#define main foo
int main(int argc, char *argv[]) {
You can also try to undef just before your main
#undef main
int main(int argc, char *argv[]) {