Я провел немало часов сегодня пытаясь понять, почему этот код segfaults на g++6.2 и g++7.0, в то же время с удовольствием работая по clang++3.9 (и 4.0).
Я уменьшил проблему до 85 строк самодостаточного фрагмента кода, который не выполняет segfault при нормальном но всегда сообщает об ошибке в UBSAN.
Проблема воспроизводится на wandbox путем компиляции с g++7, что позволяет оптимизировать и передавать -fsanitize=undefined как дополнительный флаг.
Вот что сообщает UBSAN:
prog.cc: In function 'int main()':
prog.cc:61:49: warning: 'ns#0' is used uninitialized in this function [-Wuninitialized]
([&] { ([&] { n.execute(ns...); })(); })();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
prog.cc:28:10: note: 'ns#0' was declared here
auto execute(TNode& n, TNodes&... ns)
^~~~~~~
prog.cc:30:9: runtime error: member call on null pointer of type 'struct node_then'
g++ утверждает, что ns#0 неинициализируется внутри "lambda gibberish" (который имитирует for_tuple из исходного фрагмента). Теперь происходят некоторые очень интересные вещи:
-
Если я удалю "lambda gibberish", трансформируя строку 61 в
n.execute(ns...);то UBSAN перестает жаловаться.
-
Если я меняю список захвата с
[&]на[&n, &ns...], UBSAN также перестает жаловаться:([&](auto) { ([&n, &ns...] { n.execute(ns...); })(); })(0);... подождите, что? Как это отличается от
[&]?
Применение вышеуказанных открытий к исходному фрагменту кода исправляет segfaults.
Является ли это ошибкой g++? Или есть ли в моем коде поведение undefined?
