Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::thread causes segmentation fault in Raspbian using gcc-linaro-4.9.4

I'm getting a segmentation fault on code that looks perfectly valid to me.

Here's a minimal recreating example:

#include <iostream>
#include <thread>

void func()
{
    /* do nothing; thread contents are irrelevant */
}

int main()
{
    for (unsigned idx = 0; idx < 1000; idx++)
    {
        std::thread t(func);
        void* buffer = malloc(1000);
        free(buffer);
        t.join();
    }
    return 0;
} 

I made a run with prints, to check which iteration fails; I got the segmentation fault on iteration #292.

I used gcc-linaro-4.9.4 (taken from here: https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-linux-gnueabihf/).

I compiled the program this way:

arm-linux-gnueabihf-g++ -std=c++11 -std=gnu++11 -lpthread -pthread main.cpp -o main.out

I tried recreating this in gcc-linaro-6.5, and didn't have the problem there.

Any idea why this happens?

Edit 1

There is no warnings/errors when I compile this code.

Running it under strace reveals nothing special.

Running it under GDB reveals that the segmentation faults happens in free function:

Thread 1 "main.out" received signal SIGSEGV, Segmentation fault.
_int_free (av=0x76d84794 <main_arena>, p=0x1e8bf, have_lock=0) at malloc.c:4043
4043    malloc.c: No such file or directory.
(gdb) bt
#0  _int_free (av=0x76d84794 <main_arena>, p=0x1e8bf, have_lock=0) at malloc.c:4043
#1  0x00010bfa in main ()

Running it under valgrind reveals the following:

==361== Thread 2:
==361== Invalid read of size 4
==361==    at 0x4951D64: ??? (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22)
==361==  Address 0x4becf74 is 0 bytes after a block of size 28 alloc'd
==361==    at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361==    by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361== 
==361== Invalid write of size 4
==361==    at 0x4951D6C: ??? (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22)
==361==  Address 0x4becf74 is 0 bytes after a block of size 28 alloc'd
==361==    at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361==    by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361== 
==361== 
==361== HEAP SUMMARY:
==361==     in use at exit: 28,000 bytes in 1,000 blocks
==361==   total heap usage: 2,002 allocs, 1,002 frees, 1,048,368 bytes allocated
==361== 
==361== Thread 1:
==361== 28,000 bytes in 1,000 blocks are definitely lost in loss record 1 of 1
==361==    at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361==    by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361== 
==361== LEAK SUMMARY:
==361==    definitely lost: 28,000 bytes in 1,000 blocks
==361==    indirectly lost: 0 bytes in 0 blocks
==361==      possibly lost: 0 bytes in 0 blocks
==361==    still reachable: 0 bytes in 0 blocks
==361==         suppressed: 0 bytes in 0 blocks
==361== 
==361== For counts of detected and suppressed errors, rerun with: -v
==361== ERROR SUMMARY: 2017 errors from 3 contexts (suppressed: 6 from 3)

edit 2

I still get segmetation fault after I remove the -lpthread and -std=c++11 compilation flags. This is the way I compiled it this time:

arm-linux-gnueabihf-g++ -std=gnu++11 -pthread main.cpp -o main.out
like image 471
Shachar Avatar asked Mar 14 '19 07:03

Shachar


1 Answers

I think the problem is a mismatch between your code and the libstdc++.so library you're linking to.

One possibility is that the wrong libstdc++.so is being used at runtime, which you could check by using the ldd utility. The correct version for GCC 4.9.4 is libstdc++.so.6.0.20 so if you see it linking to a different version, that's a problem.

The second possibility is that it's the right libstdc++.so but it is compiled with different settings from your code, and so the std::thread in your code uses atomic operations for shared_ptr reference counting, but the std::thread in the library uses a mutex (which is the same problem as described in GCC Bug 42734). If the crash and the valgrind errors go away when you compile your program with -march=armv5t then it would confirm this is the problem.

like image 100
Jonathan Wakely Avatar answered Nov 15 '22 21:11

Jonathan Wakely