C ++ 0x线程静态链接问题

时间:2011-08-17 09:30:33

标签: c++ multithreading c++11

我在尝试使用c ++ 0x线程功能静态链接程序时遇到了一些问题。代码看起来像这样:(编译器是Debian x86_64测试的gcc 4.6.1)

#include <iostream>
#include <thread>

static void foo() {
  std::cout << "FOO BAR\n";
}

int main() {
  std::thread t(foo);
  t.join();
  return 0;
}

我将其与:

联系起来
g++ -static -pthread -o t-static t.cpp -std=c++0x

执行程序时,出现以下错误:

terminate called after throwing an instance of 'std::system_error'
  what(): Operation not permitted
Aborted

GDB Debug输出如下所示:

Debugger finished
Current directory is ~/testspace/thread/
GNU gdb (GDB) 7.2-debian
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/will/testspace/thread/t-static...done.
(gdb) list -
1   #include <iostream>
(gdb) b 1
Breakpoint 1 at 0x4007c8: file t.cpp, line 1.
(gdb) r
Starting program: /home/will/testspace/thread/t-static 
terminate called after throwing an instance of 'std::system_error'
  what():  Operation not permitted

Program received signal SIGABRT, Aborted.
0x00000000004a8e65 in raise ()
(gdb) bt
#0  0x00000000004a8e65 in raise ()
#1  0x000000000045df90 in abort ()
#2  0x000000000044570d in __gnu_cxx::__verbose_terminate_handler() ()
#3  0x0000000000442fb6 in __cxxabiv1::__terminate(void (*)()) ()
#4  0x0000000000442fe3 in std::terminate() ()
#5  0x0000000000443cbe in __cxa_throw ()
#6  0x0000000000401fe4 in std::__throw_system_error(int) ()
#7  0x00000000004057e7 in std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>) ()
#8  0x0000000000400b18 in std::thread::thread<void (&)()> (this=0x7fffffffe540, __f=@0x4007c4) at /usr/include/c++/4.6/thread:135
#9  0x00000000004007f3 in main () at t.cpp:11
(gdb)

更新

链接静态libstdc ++可能(可能)使此错误消失,编译的C ++ 0x程序可以在没有gcc 4.6 libs的系统上运行:

g++ -static-libgcc -pthread -L.-o t thread.cpp -std=c++0x

但首先,我们应该在当前目录中建立一个符号链接'libstdc ++。a':

ln -s `g++ -print-file-name=libstdc++.a`

(参考:http://www.trilithium.com/johan/2005/06/static-libstdc/

4 个答案:

答案 0 :(得分:6)

由于我完全不知道的原因(我认为这是一个错误)你在静态链接时不能在gcc 4.6上使用std :: thread,因为函数__ghtread_active_p()将被内联为返回false(查看_M_start_thread的程序集) ),导致抛出此异常。它们可能需要pthread_create函数的弱符号,当静态链接时它们不存在,但为什么它们不这样做,否则超出我的范围(请注意,程序集后面包含callq 0x0之类的东西,那里好像出了什么问题。)

现在我个人使用boost :: threads因为我正在使用boost ...

答案 1 :(得分:6)

您应该确保链接到pthread库,否则您将收到“不允许操作”消息。

例如,要编译源代码,我会使用它:

g++ -Wall -fexceptions  -std=c++0x -g -c file.cpp -o file.o

然后与此联系:

g++ -o file file.o -lpthread

当没有目标文件时,你可以尝试这样的事情:

g++ -Wall -fexceptions -std=c++0x -g main.cpp -o file -lpthread

请记住最后保留库,因为它们仅用于链接过程。

答案 2 :(得分:6)

你可以使用-u解决问题(在gcc版本4.6.3 /(Ubuntu EGLIBC 2.15-0ubuntu10.4)中测试2.15,gcc版本4.8.1 /(Ubuntu EGLIBC 2.15-0ubuntu10.5~ppa1)2.15 )

<强> -Wl,-u,pthread_cancel可以,-u,调用pthread_cond_broadcast,-u,pthread_cond_destroy,-u,调用pthread_cond_signal,-u,调用pthread_cond_wait,-u,在pthread_create,-u,pthread_detach,-u,调用pthread_cond_signal, - U,pthread_equal,-u,在pthread_join,-u,的pthread_mutex_lock,-u,调用pthread_mutex_unlock,-u,调用pthread_once,-u,pthread_setcancelstate

<强> 1。重现错误

g++ -g -O0 -static -std=c++11 t.cpp -lpthread
./a.out
terminate called after throwing an instance of 'std::system_error'
  what():  Enable multithreading to use std::thread: Operation not permitted
Aborted (core dumped)


nm a.out | egrep "\bpthread_.*"
                 w pthread_cond_broadcast
                 w pthread_cond_destroy
                 w pthread_cond_signal
                 w pthread_cond_wait
                 w pthread_create
                 w pthread_detach
                 w pthread_equal
                 w pthread_join
                 w pthread_mutex_lock
                 w pthread_mutex_unlock
                 w pthread_once
                 w pthread_setcancelstate

<强> 2。解决错误

g++ -g -O0 -static -std=c++11 t.cpp -lpthread -Wl,-u,pthread_join,-u,pthread_equal
./a.out  
FOO BAR  


nm a.out | egrep "\bpthread_.*"  
0000000000406320 T pthread_cancel
                 w pthread_cond_broadcast
                 w pthread_cond_destroy
                 w pthread_cond_signal
                 w pthread_cond_wait
0000000000404970 W pthread_create
                 w pthread_detach
00000000004033e0 T pthread_equal
00000000004061a0 T pthread_getspecific
0000000000403270 T pthread_join
0000000000406100 T pthread_key_create
0000000000406160 T pthread_key_delete
00000000004057b0 T pthread_mutex_lock
00000000004059c0 T pthread_mutex_trylock
0000000000406020 T pthread_mutex_unlock
00000000004063b0 T pthread_once
                 w pthread_setcancelstate
0000000000406220 T pthread_setspecific

答案 3 :(得分:2)

我之前的回答已删除,我写了详细的答案。

在常见情况下,由于libpthread的链接不完整,会出现此问题。我在https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590

找到了相关信息

您可以尝试使用以下标记链接您的应用:

-Wl,--whole-archive -lpthread -Wl,--no-whole-archive

你也可以用类似的问题来看看这些问题: What is the correct link options to use std::thread in GCC under linux? Starting a std::thread with static linking causes segmentation fault