2017-02-11 9 views
0

Я использую valgrind для проверки простой многопоточной программы C++ 11. Предположим, что у вас нет ошибок, но это так.valgrind проверка простой многопоточности C++ 11 get sig11 error

исходный код следующим образом

// test_main.cpp 

#include <thread> 
#include <iostream> 
#include <string> 

std::mutex gMutex; 

void PrintLoop(const std::string& str, const uint32_t& time) 
{ 
    for (uint32_t i=0; i<time; i++) { 
     gMutex.lock(); 
     std::cout << str << ": " << i << std::endl; 
     gMutex.unlock(); 
    } 
} 

int main(int argc, char* argv[]) 
{ 
    std::thread t0(&PrintLoop, "Thread0", 100); 
    std::thread t1(&PrintLoop, "Thread1", 100); 

    t0.join(); 
    t1.join(); 
    return 0; 
} 

Я использую MacOS, и я компилировать исходный код с помощью следующей команды

g++ --std=c+=11 -g test_mian.cpp 

и выполнить с помощью следующей команды

valgrin ./a.out 

я получил следующее погрешность

==5003== Process terminating with default action of signal 11 (SIGSEGV) 
==5003== Access not within mapped region at address 0x700002ED903E 
==5003== at 0x10053A351: _pthread_find_thread (in /usr/lib/system/libsystem_pthread.dylib) 
==5003== by 0x10053B835: _pthread_join_cleanup (in /usr/lib/system/libsystem_pthread.dylib) 
==5003== by 0x10053B7C3: pthread_join (in /usr/lib/system/libsystem_pthread.dylib) 
==5003== by 0x10005BE94: std::__1::thread::join() (in /usr/lib/libc++.1.dylib) 
==5003== by 0x10000145B: main (test_main.cpp:21) 
==5003== If you believe this happened as a result of a stack 
==5003== overflow in your program's main thread (unlikely but 
==5003== possible), you can try to increase the size of the 
==5003== main thread stack using the --main-stacksize= flag. 
==5003== The main thread stack size used in this run was 8388608. 
==5003== 
==5003== HEAP SUMMARY: 
==5003==  in use at exit: 26,424 bytes in 188 blocks 
==5003== total heap usage: 259 allocs, 71 frees, 32,336 bytes allocate 
==5003== 

Memcheck: mc_leakcheck.c:1106 (void lc_scan_memory(Addr, SizeT, Bool, Int, Int, Addr, SizeT)): Assertion 'bad_scanned_addr >= VG_ROUNDUP(start, sizeof(Addr))' failed. 

host stacktrace: 
==5003== at 0x238041866: ??? 
==5003== by 0x238041C72: ??? 
==5003== by 0x238041C55: ??? 
==5003== by 0x238002FB1: ??? 
==5003== by 0x23800288C: ??? 
==5003== by 0x2380016DD: ??? 
==5003== by 0x23800EACD: ??? 
==5003== by 0x23804D221: ??? 
==5003== by 0x2380CB127: ??? 

sched status: 
    running_tid=1 

Зачем это произошло? Что-то не так с этим исходным кодом?

+0

Я не вижу проблемы с вашим кодом. Я могу запустить его в valgrind под Linux с gcc 5.4.0 без ошибок. Прохождение «времени» по ссылке меня немного задевает. Он должен работать, но попробуйте передать значение вместо этого и посмотреть, не изменит ли это что-либо. –

+0

Просто догадаться, но ... время жизни 'str' .... и' time' (^^^) –

+0

@VaughnCato: Я пробовал, но ничего не изменил, но спасибо за ваше предложение в любом случае ;-) – Qiao

ответ

1

Я пытаюсь под Ubuntu 16.04 и не получаю ошибок. Но если вы действительно хотите передать аргументы по ссылке, они должны быть завернуты в std :: ref.

1

Проблема заключается в том, что вы передаете временную ссылку на const, построенную из const char [] через конструктор создания потока ... Срок службы этого временного периода гарантируется до тех пор, пока конструктор std :: thread не вернется, что означает он скорее всего будет уничтожен до того, как дочерний поток получит доступ к нему.

Это также относится к вашему целочисленному параметру, который проявит более причудливый набор симптомов, учитывая, что это, вероятно, только немедленное сидение в регистре CPU.

Для правильной работы с вашей проблемой либо ваша функция потока принимает параметры по значению (так что существует локальная их копия), либо передает объекты, определенные в соответствующей области, в конструктор потоков по ссылке с использованием std :: исх().

0

Причина, по которой работает в новых версиях Ubuntu, - это реализация std :: string, измененная с использованием схемы подсчета ссылок на один с использованием оптимизации коротких строк. Я считаю, что изменение было сделано с помощью компилятора GCC 5.1 ... Если вы передадите строку длиной более 24 символов через конструктор std :: thread, я ожидаю, что вы все равно увидите похожие результаты.