Поддерживает ли gcc -static-libgcc с -fexceptions? - PullRequest
0 голосов
/ 15 мая 2018

Моя программа вылетает из-за ошибки при попытке развернуть стек. Это ошибка gcc или комбинация опций -fexceptions и -static-libgcc не разрешена?

Сбой не произойдет, если:

  • -static-libgcc опущено
  • -fexceptions опущен
  • Компиляция и ссылка выполняются за один шаг
  • pthread_cleanup_push() и pthread_cleanup_pop() опущены
  • Компиляция выполняется с использованием g++ или gcc -x g++ (*)

Я пробовал это на gcc 4.8.4 и 4.8.5.

(*) Это не работает для одной из наших пользовательских сред сборки, основанных на gcc 4.2.3. Тем не менее, для другой версии среды сборки, также основанной на gcc 4.2.3, сбой вообще не происходит!

Контрольный пример

/*
 * thread_crash.c: Test case for thread unwinder crash bug.
 *
 * Compile (with native or V6p3, 32 or 64 bit) using:
 *    gcc -o thread_crash.o -c thread_crash.c -ggdb -Wall -pthread -fexceptions
 *    g++ -o thread_crash thread_crash.o -ggdb -Wall -lpthread -static-libgcc
 * 
 * Expected behaviour: No output.
 * Observed behaviour: Outputs "Aborted (core dumped)".
 */

#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>

static void cleanup(void *ptr)
{
}

void *child(void *ptr)
{
  pthread_cleanup_push(cleanup, NULL);
  pthread_exit(NULL);
  pthread_cleanup_pop(1);
  return NULL;
}

int main()
{
  pthread_t foo;
  pthread_create(&foo, NULL, child, NULL);
  pthread_join(foo, NULL);
  return 0;
}

Backtrace от GDB

#0  0x00007ffff72271f7 in raise () from /lib64/libc.so.6
#1  0x00007ffff72288e8 in abort () from /lib64/libc.so.6
#2  0x00000000004031be in _Unwind_SetGR ()
#3  0x000000000040587a in __gcc_personality_v0 ()
#4  0x00007ffff6feba14 in ?? () from /lib64/libgcc_s.so.1
#5  0x00007ffff6febd64 in _Unwind_ForcedUnwind () from /lib64/libgcc_s.so.1
#6  0x00007ffff7bcd240 in __pthread_unwind () from /lib64/libpthread.so.0
#7  0x00007ffff7bc7e35 in pthread_exit () from /lib64/libpthread.so.0
#8  0x0000000000400a97 in child (ptr=0x0) at thread_crash.c:46
#9  0x00007ffff7bc6e25 in start_thread () from /lib64/libpthread.so.0
#10 0x00007ffff72ea34d in clone () from /lib64/libc.so.6

1 Ответ

0 голосов
/ 15 мая 2018

При компиляции с -fexception, pthread_exit() выдает исключение ___forced_unwind, чтобы принудительно отключить все функции, это гарантирует автоматическую очистку хранилища (он же stack ). Это потому, что pthread_exit() не предназначен для возврата. От man pthread_exit:

Эта функция не возвращает вызывающей стороне.

С другой стороны, согласно man pthread_cleanup_push:

POSIX.1 говорит, что эффект использования return, break, continue или перейти к преждевременному выходу из блока в квадратных скобках pthread_cleanup_push () и pthread_cleanup_pop () не определена. Портативные приложения должны избегайте этого.

POSIX не упоминает исключения C ++, поскольку POSIX заботится только о C, но это обоснованное предположение, что выбрасывание исключения между pthread_cleanup_push() и pthread_cleanup_pop() приводит к неопределенному поведению.

...