Я пишу игровой движок на C ++, который использует SDL для графики и OpenAL для аудио. Я занимаюсь разработкой Windows XP, компилирую с MinGW и отлаживаю с помощью GDB. Я обнаружил проблему, когда запустил отладчик, и, даже не достигнув main (), программа получила ошибку сегментации. Я был (и все еще) смущен, почему произошла ошибка, прежде чем программа достигла основного уровня. Однако, несмотря на то, что GDB сказал, что получил SIGSEGV, программа продолжила успешно и работала точно так, как я ожидал (отображенная графика, воспроизводимые звуки, музыка и т. Д.)
Конечно, будучи игровым движком, существует множество различных компонентов, поэтому я избавился от всех компонентов (исключил их из компиляции или закомментировал их) и добавил их обратно, пока не обнаружил, что мои вызовы OpenAL были вызывая segfault. Однако, как ни странно, ошибки по-прежнему происходили за до main, а комментирование вызовов функции OpenAL впоследствии приводило к тому, что segfault прекращался при следующем запуске.
Итак, чтобы проверить свою гипотезу, я сделал отдельный проект с минимальным кодом и связал его только с OpenAL32, и вуаля! Segfault. Это буквально код в полном объеме:
#include <al.h>
int main()
{
alGetError();
return 0;
}
Я могу заменить alGetError () на любой другой вызов функции OpenAL (даже alcOpenDevice (), который предназначен для первого вызова библиотеки), и возникает ошибка. Удалите alGetError (), и ошибка исчезнет.
Обратный след непосредственно в точке segfault показывает следующее:
Program received signal SIGSEGV, Segmentation fault.
0x7c918af2 in ntdll!RtlpWaitForCriticalSection ()
from C:\WINDOWS\system32\ntdll.dll
(gdb) bt
#0 0x7c918af2 in ntdll!RtlpWaitForCriticalSection ()
from C:\WINDOWS\system32\ntdll.dll
#1 0x7c901046 in ntdll!RtlEnumerateGenericTableLikeADirectory ()
from C:\WINDOWS\system32\ntdll.dll
#2 0x00e461a0 in ?? ()
#3 0x77dd6cd8 in RegCloseKey () from C:\WINDOWS\system32\advapi32.dll
#4 0x77dde88d in RegCreateKeyExA () from C:\WINDOWS\system32\advapi32.dll
#5 0x77de473f in RegCreateKeyA () from C:\WINDOWS\system32\advapi32.dll
#6 0x6650127a in ?? () from C:\WINDOWS\system32\wbsys.dll
#7 0x7c90118a in ntdll!LdrSetAppCompatDllRedirectionCallback ()
from C:\WINDOWS\system32\ntdll.dll
#8 0x66500000 in ?? ()
#9 0x7c91c342 in ntdll!LdrHotPatchRoutine ()
from C:\WINDOWS\system32\ntdll.dll
#10 0x7c915c69 in ntdll!RtlValidateUnicodeString ()
from C:\WINDOWS\system32\ntdll.dll
#11 0x7c915dcb in ntdll!LdrShutdownProcess ()
from C:\WINDOWS\system32\ntdll.dll
#12 0x00000000 in ?? ()
RtlpWaitForCriticalSection () делает его похожим на проблему потока, когда OpenAL запускается в отдельном потоке, если я не ошибаюсь. Однако я не слишком знаком с многопоточным программированием.
Я скомпилировал свой проект (весь игровой движок, в его текущем состоянии) под Linux, и сообщение segfault не появляется, и программа запускается так, как я ожидал (это означает, что есть еще пара ошибок / segfaults, которые я до сих пор надо исправить, но у меня есть ручка на них: P).
Я не совсем уверен, в чем заключается мой вопрос. Я думаю, я оставлю это с этим вопросом: сигнал segfault, который я получаю, является результатом того, как я реализую / связываю OpenAL, или это что-то вне моего контроля, которое вызывает библиотека OpenAL? Я бы предположил, что это не проблема с самим OpenAL, учитывая широкую базу пользователей библиотеки, но кто знает. Может быть, проблема в том, что я связываю свой проект C ++ с библиотекой C?
ОБНОВЛЕНИЕ : Я исследовал это в течение нескольких дней, и я очень расстроен. Единственные результаты, которые я могу найти для «Segfault перед main»: «У вас есть статический конструктор, который вызывается перед main» и «О, на самом деле это было не до main. Мне нужно научиться использовать отладчик».
Ну, я никогда не слышал о статических конструкторах в C ++. И вообще, я воспроизвел ошибку без каких-либо классов для начала. И я только сталкиваюсь с сигналом segfault, когда использую отладчик, потому что программа работает отлично, если она просто проходит через сигнал (продолжение a.k.a). Помещая точку останова в первую инструкцию в main или даже в main (), segfault происходит до того, как будет достигнута точка останова.