Understanding GCC 5's _GLIBCXX_USE_CXX11_ABI or the new ABI
Asked Answered
S

2

26

https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

I ran into crashing/valgrind issues with using std::string on GCC 5. The above link hints that there is a change in the ABI starting GCC 5.x. The new default ABI for libstd++ is C++11/14... which is not compatible with the older ABI. There is a way to select the older ABI using a define.

I am trying to understand what is the difference between the ABIs and haven't found details. I'd like help understanding:

  1. What kind of issues with std::string need to be fixed to be compatible with the new ABI? Are they copy-on-write related?
  2. Will those changes break it for older ABI?
  3. Any tips in getting _GLIBCXX_USE_CXX11_ABI to work?

More details on the issue I ran into (https://github.com/YasserAsmi/jvar/issues/21) The project worked fine in GCC 4.8 and Clang. With GCC, the same code refuses to run:

x_misc(33112,0x7fff728c2000) malloc: *** error for object 0x7fd639c034cc:    pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

And here is a partial Valgrind output:

==33027== Invalid read of size 1
==33027==    at 0x1006F78BA: _platform_memmove$VARIANT$Nehalem (in /usr/lib/system/libsystem_platform.dylib)
==33027==    by 0x100009388: jvar::Variant::toString[abi:cxx11]() const (in bin/ex_misc)
==33027==    by 0x1000023A7: bugreport() (in bin/ex_misc)
==33027==    by 0x1000133B8: main (in bin/ex_misc)

The project uses std::string and has some custom memory management. It is doing some non-typical but valid operations using placement new constructors etc. I am trying to understand better what kind of code is effected by the API and how to fix it--a place to start.

Subjunctive answered 2/1, 2016 at 22:56 Comment(1)
If you're compiling all objects consistently (with the same ABI), then the errors you're getting are due to errors in your program or (less likely) an actual bug in the new ABI implementation. In either case, work it down to a small test case and post here (a minimal reproducible example).Kopje
L
14
  1. The old std::string was not compliant with C++11 because that standard prohibits a copy-on-write implementation. There was no way to create a compliant std::string without breaking ABI, so they did so with a way to return to the non-compliant version for ABI compatibility.

  2. Yes.

  3. Make sure all the translation units in your program use the same value of _GLIBCXX_USE_CXX11_ABI and you should be fine. If you mix them up across translation units you will definitely have problems. You might be ok if you have different values of the define in different translation units that don't communicate strings to each other.

Limicolous answered 2/1, 2016 at 23:27 Comment(8)
On #1, what exact type of old code would be breaking with the new ABI. What can I look for in my old code with std::strings and fix it? ThanksSubjunctive
Good answer. For what it is worth, in Debian we resorted to recompiling everything as per point 3. See eg this wiki entry for more.Esthonia
@YasserAsmi There's nothing to fix, the new ABI just requires everything you link together to use the same ABI.Mordecai
@nos, I updated the original post... My project that worked fine in GCC 4.8 and CLANG doesn't work in GCC 5. Other projects reported similar issue: example: github.com/facebook/folly/issues/316Subjunctive
You probably need to recompile. Everything. That's what I did with the R stack at work using various C++-based packaged.Esthonia
@DirkEddelbuettel, I am doing a clean build of the project (lib and apps) and it doesn't link to any other libs.. May be CMake is adding some libs?Subjunctive
@DirkEddelbuettel, Thanks... Did you recompile everything with the _GLIBCXX_USE_CXX11_ABI defined as 0? I am rebuilding everything as is.Subjunctive
Yes. Following the upgrade to Ubuntu 15.10 with g++ 5.2 which got us new system libraries, everything from in-house was rebuilt. You have to.Esthonia
G
5

There is an interesting difference between COW and non-COW string for example:

std::string some_string;
std::string foo()
{
   return some_string;
}

char const *s = foo().c_str();
printf("%s\n",s);

This would work with COW strings as c_str() that is returned by some_string and foo point to same memory but when it isn't COW than s would be invalidated once std::string returned by foo is destroyed.

From the sample there you should look into this direction.

Grouty answered 3/1, 2016 at 15:38 Comment(4)
K... but isn't this still Undefined Behaviour by attempting to use the pointer extracted from the temporary std::string created as the return value from foo()? Since COW was allowed, but not required, you can't assume that it was in play.Faculty
It is undefined behavior but it can lead to hidden bug when the strings are COW and than using non COW strings.Grouty
You're blaming the wrong thing then. The hidden bug is because of Undefined Behaviour, not on the existence of COW. No different than dereferencing nullptr causing (or not causing) one's program to crash.Faculty
I'm not blaming I'm explaining how with old ABI it may work and with new not - and code seems to have features like thatGrouty

© 2022 - 2024 — McMap. All rights reserved.