Check following main.cpp
:
# cat main.cpp
#include <functional>
#include <thread>
int main()
{
int a = 2;
std::function<void ()> work = [&]()
{
if (a < 1) {
return 1;
}
while (1)
{
if (a > 1)
{
break;
}
}
};
std::thread t(mergeWork);
t.join();
return 0;
}
The prototype of work
is void ()
, while in a < 1
branch, it actually has a return value:
if (a < 1) {
return 1;
}
Compile the program with g++
, and execute it:
# g++ -g -pthread main.cpp
# ./a.out
#
It runs smoothly. Switch to clang++
:
# clang++ -g -pthread main.cpp
main.cpp:20:5: warning: control may reach end of non-void lambda [-Wreturn-type]
};
^
1 warning generated.
# ./a.out
Illegal instruction (core dumped)
A warning is generated during building and “Illegal instruction
” occurs during running. Check the assembly code of work
:
disassemble
Dump of assembler code for function main::$_0::operator()() const:
0x0000555555555100 <+0>: push %rbp
0x0000555555555101 <+1>: mov %rsp,%rbp
0x0000555555555104 <+4>: mov %rdi,-0x8(%rbp)
0x0000555555555108 <+8>: mov -0x8(%rbp),%rdi
=> 0x000055555555510c <+12>: mov (%rdi),%rax
0x000055555555510f <+15>: cmpl $0x1,(%rax)
0x0000555555555112 <+18>: mov %rdi,-0x10(%rbp)
0x0000555555555116 <+22>: jge 0x555555555123 <main::$_0::operator()() const+35>
0x000055555555511c <+28>: mov $0x1,%eax
0x0000555555555121 <+33>: pop %rbp
0x0000555555555122 <+34>: retq
0x0000555555555123 <+35>: jmpq 0x555555555128 <main::$_0::operator()() const+40>
0x0000555555555128 <+40>: mov -0x10(%rbp),%rax
0x000055555555512c <+44>: mov (%rax),%rcx
0x000055555555512f <+47>: cmpl $0x1,(%rcx)
0x0000555555555132 <+50>: jle 0x55555555513d <main::$_0::operator()() const+61>
0x0000555555555138 <+56>: jmpq 0x555555555142 <main::$_0::operator()() const+66>
0x000055555555513d <+61>: jmpq 0x555555555128 <main::$_0::operator()() const+40>
0x0000555555555142 <+66>: ud2
End of assembler dump.
We can find an ud2
instruction at the end of lambda function. Modify the a < 1
branch:
if (a < 1) {
return;
}
This time, the program runs OK.