0
votes

My program terminated with a Segmentation Fault. I reduced the code down to this:

#include <string>
#include <omp.h>
#include <iostream>

namespace ns { // Holds three strings
    static const std::string A = "a";
    static const std::string B = "b";
    static const std::string C = "c";
}

namespace ns2 {
    // Wraps an ostream and a lock; for example, concurrent access
    // can be implemented this way
    class wrapper { 
    private:
        std::ostream &_stream;
        omp_lock_t _lock;
    public:
        wrapper(std::ostream &stream) : _stream(stream)
        {
            omp_init_lock(&_lock);
        }
        // Segmentation Fault also occurs without destructor
        ~wrapper()
        {
            omp_destroy_lock(&_lock);
        }
    };
    // Wrap stdout
    static wrapper cout(std::cout);
}

namespace ns3 {
    struct somestruct {
        const std::string _0;   
        const std::string _a;
        const std::string _b;
        const std::string _c;
        somestruct(std::string o, std::string a, std::string b, std::string c)
            : _0(o), _a(a), _b(b), _c(c) { }
    };
}

int main(int argc, char *argv[])
{   
    ns3::somestruct cont("0", ns::A, ns::B, ns::C);
    return 0;
}

I am compiling on MacOS:

System Version: OS X 10.11.6 (15G22010)
Kernel Version: Darwin 15.6.0

using g++-7:

g++-7 (Homebrew GCC 7.5.0_1) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

and the command line is g++-7 file.cpp -O1 -fopenmp

The Segmentation Fault also occurs for -O2 and -O3, but not for -O0. Strangely, it only occurs on this machine and none of my other machines or godbolt.

I ran valgrind on the executable. This is the output:

==54305== Memcheck, a memory error detector
==54305== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==54305== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==54305== Command: ./a.out
==54305==
==54305== Invalid read of size 1
==54305== at 0x100000906: void std::__cxx11::basic_string, std::allocator >::_M_construct(char const*, char const*, std::forward_iterator_tag) [clone .isra.23] (basic_string.h:338)
==54305== by 0x1000009EC: main (basic_string.h:236)
==54305== Address 0x4d55545a4d55545a is not stack'd, malloc'd or (recently) free'd
==54305==
==54305== Signal 11 being dropped from thread 0's queue

followed by an infinite loop of

==54305== Signal 11 being dropped from thread 0's queue

I have to use kill to stop memcheck after that, it does not react to Ctrl+C. See also this question for a similar response from valgrind. However, there seems to be a different cause here.

I cannot use gdb at the moment, because I have to codesign it (which I don't think is possible solely via terminal/ssh).

Another interesting thing is that if I comment out the line ns3::somestruct cont("0", ns::A, ns::B, ns::C); instead of simply printing

Segmentation fault: 11

the output of the program becomes

a.out(54371,0x7fff77d7d000) malloc: *** error for object 0x4d55545a4d55545a: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

I do not see, where the Segmentation Fault would come from. Did I miss something?

Edit

I have managed to get gdb working. This is the output:

[New Thread 0x1703 of process 55870]
Program received signal SIGSEGV, Segmentation fault.
warning: `/private/tmp/gcc@7-20200229-63593-evr5eg/gcc-7.5.0/build/x86_64-apple-darwin15.6.0/libstdc++-v3/src/.libs/compatibility-atomic-c++0x.o': can't open to read symbols: No such file or directory.
[Followed by a lot more warnings like that]
Program received signal SIGSEGV, Segmentation fault.
std::__cxx11::basic_string, std::allocator >::_M_construct (this=0x7fff5fbffb70, __beg=0x4d55545a4d55545a , __end=)
(gdb) where
#0 std::__cxx11::basic_string, std::allocator >::_M_construct (this=0x7fff5fbffb70, __beg=0x4d55545a4d55545a , __end=)
#1 0x0000000100000a2f in main (argc=, argv=) at /usr/local/Cellar/gcc@7/7.5.0_1/include/c++/7.5.0/bits/basic_string.h:236

I still don't understand, why this happens. I recently updated homebrew and ever since then this "bug" seems to occur and since then this bug occurs. Any ideas on which library might need an update or similar?

Edit 2

Again, commenting out the first line of main moves the problem:

a.out(55934,0x7fff77d7d000) malloc: *** error for object 0x4d55545a4d55545a: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

Program received signal SIGABRT, Aborted.
0x00007fff88204f06 in __pthread_kill () from /usr/lib/system/libsystem_kernel.dylib
(gdb) where
#0 0x00007fff88204f06 in __pthread_kill () from /usr/lib/system/libsystem_kernel.dylib
#1 0x00007fff8c40d4ec in pthread_kill () from /usr/lib/system/libsystem_pthread.dylib
#2 0x00007fff8b7f06df in abort () from /usr/lib/system/libsystem_c.dylib
#3 0x00007fff88273041 in free () from /usr/lib/system/libsystem_malloc.dylib
#4 0x00007fff8b7f1463 in __cxa_finalize_ranges () from /usr/lib/system/libsystem_c.dylib
#5 0x00007fff8b7f1767 in exit () from /usr/lib/system/libsystem_c.dylib
#6 0x00007fff939de5b4 in start () from /usr/lib/system/libdyld.dylib
#7 0x0000000000000000 in ?? ()

Edit 3

otool -L (ldd is not available on this machine, but according to this discussion it should be equivalent) gives the following output:

a.out:
/usr/local/opt/gcc@7/lib/gcc/7/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.24.0)
/usr/local/opt/gcc@7/lib/gcc/7/libgomp.1.dylib (compatibility version 2.0.0, current version 2.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
/usr/local/lib/gcc/7/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

I will add what happens for gcc@9 as soon as it is reinstalled, but I remember from a previous install, that the behaviour should be identical.

The behaviour is identical with g++-9. The otool -L output shows the version 9 variants of the dylibs except for /usr/lib/libSystem.B.dylib which is identical in this case.

Can anyone reproduce this bug?

Edit 4

I used otool -L on an older version of the executable I compiled before I updated homebrew. It references

/usr/local/opt/gcc@7/lib/gcc/7/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.23.0)

while all other libraries are the same version. Additionally, the g++-9 compiled executable also references version 7.24.0. Maybe this causes the bug? How do I reinstall this older version of libstdc++ to test this hypothesis? I forced brew to reinstall g++ version 7.1.0 which uses version 7.23.0 of libstdc++. The bug persists.

1
Did you test with newer version of GCC such as GCC-8 and GCC-9? what is the result of ldd on the generated executable?Jérôme Richard
@JérômeRichard I have added some information.HerpDerpington
When you have a problem in the STL, it is likely that the version of the header and the dynamic library does not use the same version and are incompatible together. The version you have is suspicious since the so file indicate version 6 and otool the version 7. Additionally, from the GCC documentation we can see that GCC should use an older version (but maybe the version 7.23 is compatible with 6.xx versions, although that would be surprising).Jérôme Richard

1 Answers

0
votes

After I did a lot of trying around, I finally decided to upgrade the operating system to macOS Mojave. This resolved the problem, after I brew reinstalled everything. (However, note that valgrind does not seem to be available for Mojave yet. Furthemore, I had noticed more problems in other software such as gnuplot, where the programs would not start properly.)

Note that brew warned me that there might be problems when trying to use it on the old macOS version and that it is technically no longer supported. Furthermore, I updated Xcode and clang, which were also outdated for a long time.

Therefore, this problem seems to be caused by some sort of version mismatch between the OS, brew/clang and the gnu compiler.