2012-03-30 140 views
7

代碼:的std ::線程創建拋出異常

#include <iostream> 
#include <thread> 

void hello() 
{ 
    std::cout << "Hello World" << std::endl; 
} 

int main() 
{ 
    try 
    { 
     std::cout << "creating thread" << std::endl; 
     std::thread t(hello); 
     std::cout << "waiting" << std::endl; 
     t.join(); 
     std::cout << "done" << std::endl; 
    } 
    catch(std::exception& ex) 
    { 
     std::cout << ex.what() << std::endl; 
    } 
} 

體形:

g++ -Wall -fexceptions -std=c++0x -pthread -g  -c /home/alex/tmp/thread_test/main.cpp -o obj/Debug/main.o 
g++ -o bin/Debug/thread_test obj/Debug/main.o  
Output size is 106.62 KB 
Process terminated with status 0 (0 minutes, 0 seconds) 
0 errors, 0 warnings 

結果:

創建線程
操作不允許

這是如何解決的?

編輯:
與strace的運行程序:

[email protected]:~/tmp/thread_test/bin/Debug$ strace ./thread_test 
execve("./thread_test", ["./thread_test"], [/* 38 vars */]) = 0 
brk(0)         = 0x189a000 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c60cbc000 
access("/etc/ld.so.preload", R_OK)  = -1 ENOENT (No such file or directory) 
open("/etc/ld.so.cache", O_RDONLY)  = 3 
fstat(3, {st_mode=S_IFREG|0644, st_size=121299, ...}) = 0 
mmap(NULL, 121299, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7c60c9e000 
close(3)        = 0 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
open("/usr/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY) = 3 
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\244\5\0\0\0\0\0"..., 832) = 832 
fstat(3, {st_mode=S_IFREG|0644, st_size=991424, ...}) = 0 
mmap(NULL, 3171440, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7c60797000 
mprotect(0x7f7c6087f000, 2097152, PROT_NONE) = 0 
mmap(0x7f7c60a7f000, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xe8000) = 0x7f7c60a7f000 
mmap(0x7f7c60a89000, 83056, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7c60a89000 
close(3)        = 0 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
open("/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY) = 3 
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260(\0\0\0\0\0\0"..., 832) = 832 
fstat(3, {st_mode=S_IFREG|0644, st_size=88384, ...}) = 0 
mmap(NULL, 2184216, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7c60581000 
mprotect(0x7f7c60596000, 2093056, PROT_NONE) = 0 
mmap(0x7f7c60795000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14000) = 0x7f7c60795000 
close(3)        = 0 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3 
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \24\2\0\0\0\0\0"..., 832) = 832 
fstat(3, {st_mode=S_IFREG|0755, st_size=1685816, ...}) = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c60c9d000 
mmap(NULL, 3801960, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7c601e0000 
mprotect(0x7f7c60377000, 2093056, PROT_NONE) = 0 
mmap(0x7f7c60576000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x196000) = 0x7f7c60576000 
mmap(0x7f7c6057b000, 21352, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7c6057b000 
close(3)        = 0 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
open("/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY) = 3 
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360>\0\0\0\0\0\0"..., 832) = 832 
fstat(3, {st_mode=S_IFREG|0644, st_size=538928, ...}) = 0 
mmap(NULL, 2633960, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7c5ff5c000 
mprotect(0x7f7c5ffdf000, 2093056, PROT_NONE) = 0 
mmap(0x7f7c601de000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x82000) = 0x7f7c601de000 
close(3)        = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c60c9c000 
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c60c9a000 
arch_prctl(ARCH_SET_FS, 0x7f7c60c9a740) = 0 
mprotect(0x7f7c601de000, 4096, PROT_READ) = 0 
mprotect(0x7f7c60576000, 16384, PROT_READ) = 0 
mprotect(0x7f7c60795000, 4096, PROT_READ) = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c60c99000 
mprotect(0x7f7c60a7f000, 32768, PROT_READ) = 0 
mprotect(0x603000, 4096, PROT_READ)  = 0 
mprotect(0x7f7c60cbe000, 4096, PROT_READ) = 0 
munmap(0x7f7c60c9e000, 121299)   = 0 
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c60cbb000 
write(1, "creating thread\n", 16creating thread 
)  = 16 
brk(0)         = 0x189a000 
brk(0x18bb000)       = 0x18bb000 
write(1, "Operation not permitted\n", 24Operation not permitted 
) = 24 
exit_group(0)       = ? 
+0

哪個版本的gcc? – mark 2012-03-30 15:12:49

+0

g ++(Ubuntu/Linaro 4.6.1-9ubuntu3)4.6.1 – 2012-03-30 15:42:41

+1

做「strace」,看看系統調用拒絕你用「不允許」。它與你的代碼無關,更多的是權限,進程屬性等(如ulimit) – 2012-03-30 16:22:54

回答

11

你的問題是,你忘了指定-lpthread-pthread標誌的編譯器。因此,在構建程序時,它假定採用單線程模式。

唯一的例外是由C++標準庫拋出:

(gdb) catch throw 
Function "__cxa_throw" not defined. 
Catchpoint 1 (throw) 
(gdb) run 
Starting program: /tmp/test 
creating thread 
Catchpoint 1 (exception thrown), 0x00007ffff7b8eff0 in __cxa_throw() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
(gdb) where 
#0 0x00007ffff7b8eff0 in __cxa_throw() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#1 0x00007ffff7b3ba3e in std::__throw_system_error(int)() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#2 0x00007ffff7b45cb7 in std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>)() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#3 0x00000000004012d4 in std::thread::thread<void (&)()>(void (&&&)())() 
#4 0x0000000000400f0e in main() 
(gdb) quit 

我沒有檢查該源代碼的任何願望,但它是最有可能的,他們使用「懶惰」的動態鏈接,以確定是否POSIX線程系列功能可用。然後拋出異常。這樣,除非與pthread庫鏈接,否則會得到該異常。

這與虛擬內存或其他資源限制無關,因爲我最初認爲可能會發生這種情況,因爲系統調用不報告任何錯誤。所以只是做:

g++ -std=c++0x -o test ./test.cpp -pthread 

...它會工作。

UPDATE:

由於@ildjaRN指出的那樣,你已經指定-pthread。我建議你在你的目標文件(單個調用編譯&鏈接的源文件)之後指定它,否則它可能不會被拾取。

這裏是如何確保它撿起 - 你可以運行ldd,並確保pthread.so使得它在:

$ g++ -std=c++0x -lpthread -o test ./test.cpp 
$ ldd ./test | grep pthread 
$ g++ -std=c++0x -o test ./test.cpp -lpthread 
$ ldd ./test | grep pthread 
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff2a9073000) 
$ 

希望它能幫助。祝你好運!

+0

他的g ++調用特別是_does_具有'-pthread'。 – ildjarn 2012-03-30 17:08:13

+2

@ildjarn:你通常必須在對象文件之後指定庫,否則它們不會被拉入。在某些版本的gcc(4.6.1我相信)中存在鏈接器的錯誤,但事情並非如此,後來得到修復。 – 2012-03-30 17:10:37

+0

看起來這個問題真的是在-pthread開關中。把它移到最後並沒有幫助。執行ldd。/ thread_test | grep pthread不會產生任何輸出。 – 2012-03-30 18:49:48