Falha de segmentação no gcc causada pelo wrapper lambda durante a chamada de função do modelo variada
Passei algumas horas hojetentando entender por queesse código segfaults emg++6.2
eg++7.0
, trabalhando alegremente como planejadoclang++3.9
(e4.0
).
Reduzi o problema para umSnippet de código independente de 85 linhas, qualnão segfault na execução normal, massempre relata um erro no UBSAN.
O problemaé reproduzível na caixa de varinha, compilando comg++7
, permitindo otimizações e aprovação-fsanitize=undefined
como uma bandeira extra.
É isso que a UBSAN relata:
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++
afirma quens#0
é não inicializado dentro da "linguagem lambda"(que simula ofor_tuple
do snippet original). Agora, algumas coisas muito interessantes ocorrem:
Se eu remover o "jargão lambda", transformandolinha 61 para dentro
n.execute(ns...);
então o UBSAN para de reclamar.
E seEu mudo a lista de captura de[&]
para[&n, &ns...]
, O UBSAN também para de reclamar:
([&](auto) { ([&n, &ns...] { n.execute(ns...); })(); })(0);
...espere o que? Como isso é diferente de[&]
?
Aplicando as descobertas acima ao snippet de código originalcorrige os segfaults.
Isso é umg++
erro? Ou existe algum comportamento indefinido no meu código?