I recently spent a fairly substantial amount of time tracking down a problem that turned out to be caused by compiling a library with -D_GLIBCXX_DEBUG (which tells libstdc++ to use a debug version of the standard library with extra checks) but compiling the client program without. This caused an ABI compatibility problem.
Is there some way I can automatically detect problems like this with GCC? Visual Studio provides the detect_mismatch pragma which I think would have served this purpose, but I'm unaware of any GCC equivalent. GCC does something with embedding a symbol name (e.g. GLIBCXX_3.4.9), and I can imagine schemes that would cause a linking error because of an undefined symbol if a corresponding symbol (e.g. mylib_debug_stl) were not present, but the only ways I can think of to get a use of that symbol are really hacky.
Alternatively, how do other people avoid this issue? Build the checked version of the library to a different name or something like that?
Is there some way I can automatically detect problems like this with GCC?
Only the linker can detect if you link incompatible code, not the compiler.
The alternative linker, gold, can detect some problems with the --detect-odr-violations option.
Alternatively, how do other people avoid this issue? Build the checked version of the library to a different name or something like that?
I just ensure I rebuild everything when I want to use the Debug Mode, I don't think I've ever wanted to keep a library around that was built with Debug Mode. It's meant for debugging, not for normal use.
I rarely use -D_GLIBCXX_DEBUG anyway, I more often do something like:
#if 0
# include <debug/vector>
namespace my_class_stl = __gnu_debug;
#else
#include <vector>
namespace my_class_stl = std;
#endif
struct my_class
{
typedef my_class_stl::vector<int> container;
typedef container::iterator iterator;
// ...
};
Then I change the preprocessor condition when I want to use a Debug Mode vector for that specific class, without affecting every container in the program. Because the change involves writing to the file (and so updating its timestamp) anything that depends on that header will get rebuilt by make, and there are two distinct types, std::vector<int> and __gnu_debug::vector<int>, which have different symbols and can't be confused by the linker.
Just defining _GLIBCXX_DEBUG doesn't cause all dependencies to be rebuilt, and silently alters the definition of std::vector globally, rather than changing specific containers to a different type with a different name, __gnu_debug::vector
turned out to be caused by compiling a library with -D_GLIBCXX_DEBUG (which tells libstdc++ to use a debug version of the standard library with extra checks) but compiling the client program without.
It is an explicit libsdc++ debugging mode design goal to support such configuration, and I somewhat doubt that that was the actual cause of your problem.
The problem may have disappeared after you rebuilt the library without -D_GLIBCXX_DEBUG, but that doesn't prove that the ABI incompatibility was the root cause.
Related
I have some C++ code using NEON intrinsics. From what I have read, all you need to do is include arm_neon.h to your project.. And then I read that this arm_neon.h header is not actually readily available to you automatically, you have to get it from the web. So I found and added this version to my project:
http://clang.llvm.org/doxygen/arm__neon_8h-source.html
In my project's prefix.pch I added:
#import "arm_neon.h"
And when I try to build on my iPhone6 device (I am not using the simulator), I get a billion errors inside the arm_neon.h file:
Can anyone please explain to me what I am missing here?
You've been misinformed about being able to pick up an arm_neon.h from the Internet. Generally the header is not just compiler specific, but compiler version (even compiler revision) specific. For GCC it relies on a number of compiler built in function calls, and from your screenshot of Clang the same holds there. As you'd expect, if the name of these internal-only functions changes, the header will fail to compile.
What surprises me is that you're unable to use an include of whichever arm_neon.h ships with your build environment. The only thing I can think of that would cause this is the build command trying to build for x86_64 (for the simulator) but you say this isn't what is happening. It might be worth checking your build settings one more time.
If you're still not getting anywhere, remember that arm_neon.h is sometimes considered as a system header, so in C++ you might need to #include <arm_neon.h> rather than #include "arm_neon.h" to get the compiler to search the system paths.
I am giving Gwan a whirl.
Having made it through example code, I started a small project with more than one source file. I now have two problems:
I got a linking error at server startup:
Linking main.cpp: undefined symbol: _ZN7GwanUrl9concatAllEv
(the main file #includes the two other files; all the files are in the csp directory)
As an alternative to having all the files in the /csp directory, I would like to make a library outside of the /csp directory while still using some of the gwan functions. sadly, a tonne of errors follow -- WHEN I GCC from commandline not via G-WAN Startup.
In file included from /home/ec2-user/gwan/include/gwan.h:22,
from Xbufstream.h:10,
from Xbufstream.cpp:10:
/usr/include/time.h:199: error: ‘size_t’ does not name a type
.....
Anyone knows what the gwan g++ argument string looks like?
(odd the 1. and 1. its 1. and 2. in the editor)
First, this is not a linker issue: you have "undefined symbol" rather than "unresolved symbol" as an error.
This is simply an #include issue.
define the main() function in your script.cpp file.
there's a G-WAN folder dedicated to user-defined include files called /gwan/include but you can as well use /csp/my_include.hpp... if you are using the right syntax:
For example, having #include "toto.hpp" in /csp/hello.cpp lets me reach C++ functions defined and implemented in the gwan/include/toto.hpp file (or defined in toto.hpp and implemented in a pre-compiled library linked to your script with #pragma link).
If you rather use #include <toto.hpp> then the SYSTEM INCLUDE PATH will be searched instead (and this will work providing that your library was correctly installed).
If you want to use #include "toto.hpp" for a custom folder that was not setup in the system, you can use G-WAN's #pragma include "../my_folder" directive to specify its PATH or you can explicitely specify it in each include: #include "../my_folder/toto.hpp".
Nothing fancy there, only C/C++ dependancy rules apply (and G-WAN really helps by providing alternate ways that do not involve system settings).
For libraries (see the G-WAN examples for SQLite, Cairo, mySQL, cURL, etc.) you can either use pre-installed libraries that exported their location in SYSTEM variables... or put your library in the /gwan/libraries folder and their include file in the /gwan/include folder.
When writing your own libraries, remember that they need to be pre-compiled. This means that you obviously cannot use G-WAN symbols since your compiler may #include "gwan.h" (to have the definitions) but your linker will not know from where G-WAN symbols can be found. The way around is to always use the G-WAN API from the G-WAN scripts. Your custom libraries must either be general-purpose or buffer any payload intended to be used by G-WAN. No-double copy is needed since G-WAN provides the set_reply() call to let G-WAN use persistent replies built without the reply xbuffer provided by G-WAN servlets.
Now, a last word about linking (which was not the cause of your trouble but could participate to the confusion). If you mix C and C++, use extern C {} to wrap your C++ prototypes called from C (otherwise you will really have "unresolved symbols").
With all this information, you should be ready to face every possible situation.
the issue of referencing gwan.h symbols inside #include files can also be solved by moving all code into the header file, whether its .h or .hpp
its ungraceful but a fix nevertheless. and good enough for the simple extension i wanted.
looking into the /libraries/sqlite3/sqlite.h helped.
#gil, thanks for your time.
I think I found a bug in the libc++ list implementation. The following code will produce a compiler error (Field has incomlete type 'foo') when using certain build settings in xcode:
#include <list>
using namespace std;
class foo {
public:
list<foo> bar;
};
The settings are the following:
XCode Version: 4.4.1
C++ Language Dialect: C++11 or GNU++11
C++ Standard library: LLVM C++ standard library with C++ extensions (libc++11)
Using GCCs libstdc++ will resolve the error.
Not using the C++11 dialect will resolve the error.
Using vector instead of list will resolve the error.
I think it is a bug in the list implementation, but I am not sure.
Forgive my ignorance, but I don't know what I should do to resolve this issue.
Switching to vector is not an option in my project and I definitely need C++11 features. That also includes shared_ptr, but the headers are missing when using GCC. Beside that, apple does not seem to provide new versions of GCC anymore.
I would very appreciate it if somebody could recreate this issue, maybe with newer header from libc++.
Also, if updating LLVM/libc++ would resolve this issue, do you recommend it?
C++ Standard 17.6.4.8:
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
...
if an incomplete type (3.9) is used as a template argument when instantiating a template component,
unless specifically allowed for that component.
None of the standard library's container class templates, including list, mention any such allowance for an incomplete type. So your program is an invalid one that might happen to work with some compilers. That can't be considered a bug in the standard library implementation.
We have Oracle 11 running on HP-UX 11.31 and gcc 4.4.3. It seems that there is no way to link to occi, because it was built with aCC. Is there any workaround for this?
I had the silly idea that I could somehow build a library that basically proxied the connection - build the library with aCC in some way that could be linked to by gcc. Is this possible?
No, there isn't a way around that.
Different C compilers have interchangeable code using a standard ABI. You can mix and match their object code more or less with impunity.
However, different C++ compilers have a variety of different conventions that mean that their object code is not compatible. These relate to class layout (especially in multiple inheritance hierarchies and the dreaded 'diamond-of-death'), but also in name mangling conventions and exception handling. The name mangling schemes are deliberately made different so that you cannot accidentally link objects from one compiler with another.
Generally, if libraries are built using a C++ compiler, you have to link your code using the same - or at least a compatible - C++ compiler. And that almost invariably means a compiler from the same family. For example, you might be able to use G++ 4.5.0 even if the code was built with G++ 4.4.2. However, you won't be able to mix aCC with G++.
When developing and deploying native Windows applications, I often need to install a runtime before being able to run my binary, or statically link the library with my binary. For instance, after building a "Win32 Console" project with Visual Studio 2008, attempting to run the program on a fresh Windows 7 image results in:
The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
Issues like this one have been brought up in other posts on StackOverflow.
How does one develop applications that don't require runtimes that aren't already on the target OS (i.e. don't require installing redistributable packages or private/shared side-by-side assemblies)? How does one avoid using msvc[mpr]90.dll and just use the Windows API in \windows\system32*.{dll,sys}?
I'm thinking along the lines of the code that comes out of the demoscene, but that's frequently not made available.
Others have already responded with respect to linking CRT statically. If you also want a small binary at the same time, then your best bet is forego CRT entirely, and use only Win32 API functions as much as possible. You'll still get some CRT code, most notably related to startup (i.e. that which calls main) and shutdown (atexit handling etc), but otherwise the linker won't link CRT functions that you do not use.
You can avoid linking CRT altogether by using /Zl compiler switch. This means that main will no longer work, however - you'll need to define WinMain (name doesn't matter, but signature must match, and it must be __stdcall), and you will have to specify the name of your WinMain-like function as an entry point via linker /entry: switch. This will save you ~30Kb of CRT code (tested on a .cpp with an empty main).
If you go the latter route, you might also have to deal with issue of compiler intrinsics. There are some functions that are nominally defined by the CRT (and declared in its headers), but which are treated specially by the compiler, so that it inserts optimized assembly instructions at the point of the call where possible - examples are memset, strlen, and a good chunk of functions in <math.h>; a complete list can be found here. Since you don't have CRT, if you need these functions, or could avoid it but prefer the intrinsic because of improved performance (hard to do better than memset, for example), then you have to declare them yourself, and use #pragma intrinsic. E.g.:
// Contains macros and typedef only, so safe to include without CRT.
// We need it here for size_t.
#include <stddef.h>
extern "C"
{
int abs(int);
void* memset(void*, int, size_t);
}
#pragma intrinsic(abs, memset)
int __stdcall main(void*, void*, char*, int)
{
char tmp[10];
memset(tmp, abs(-123), 10);
return 0;
}
The above can be compiled with:
cl /c /Zl foo.cpp
link /entry:main foo.obj
Link the CRT statically via the /MT switch (and likewise MFC, if you're using it).
Static linking limits what you can do with DLLs somewhat, but for simple executables it works like a charm. (And if you're shipping DLLs, you can always ship private assemblies anyway.)
Use the static CRT. This doesn't create a dependency on msvc*.dll. The CRT is linked directly into your program. This doesn't create dependencies, but does increase the size of your executable.
More info on different CRT options here.
Statically link the runtime. MS Visual C++ has option /MT for that (default is /MD)
I think one way to do this is to just not use Visual Studio and instead rely on the command line SDK tools. (You can alternatively figure out how to config VS to do what you want, but that seems harder.) E.g.:
cl /c app.cpp
link app.obj ws2_32.lib