Проблема статического связывания потока C ++ 0x - PullRequest
10 голосов
/ 17 августа 2011

У меня возникли некоторые проблемы при попытке статически связать программы, используя функции потоков c ++ 0x.Код выглядит так: (Компилятор gcc 4.6.1 при тестировании Debian x86_64)

#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 выглядит следующим образом:

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:

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 ]

6 голосов
/ 08 августа 2012

Вы должны убедиться, что вы связываетесь с библиотекой 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

Не забудьте оставить библиотеки в конце, так как они будут использоваться только в процессе компоновки.

6 голосов
/ 05 января 2015

вы можете использовать -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, - и, 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
6 голосов
/ 17 августа 2011

По неизвестным мне причинам (я считаю это ошибкой) вы не можете использовать std :: thread в gcc 4.6 при статическом линковании, поскольку функция __ghtread_active_p () будет встроена как возвращающая false (посмотрите на сборку _M_start_thread ), вызывая это исключение. Возможно, им требуются слабые символы для функции pthread_create, и когда они статически связаны, их там нет, но почему они не делают этого, иначе я не понимаю (обратите внимание, что сборка позже содержит такие вещи, как callq 0x0, кажется, идти что-то очень неправильно).

На данный момент я лично использую Boost :: Threads, так как я в любом случае использую Boost ...

2 голосов
/ 07 июля 2015

Мой предыдущий ответ был удален, и я написал подробный ответ.

В общих случаях эта проблема возникает из-за неполного связывания libpthread.Я нашел информацию об этом здесь https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590

Вы можете попробовать связать ваше приложение со следующими флагами:

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

Также вы можете посмотреть на эти вопросы с похожей проблемой: Как правильно выбрать ссылку для использования std :: thread в GCC под linux? Запуск std :: thread со статическим связыванием вызывает ошибку сегментации

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...