Какие последствия вызова функции с ошибкой no return statement in function returning non-void?
Есть такой код:
void func1()
{
std::cout << "func1" << std::endl;
}
void func2()
{
std::cout << "func2" << std::endl;
}
bool func3()
{
std::cout << "func3" << std::endl;
func1();
func2();
}
int main(int argc, char* argv[])
{
func3();
return 0;
}
как можно видеть в функции bool func3() ошибка: функция не возвращает значение. Если скомпилировать эту программу:
g++ -O2 main.cpp
то получим следующее поведение
func3
func1
func2
func3
func1
func2
Ошибка сегментирования (стек памяти сброшен на диск)
Вопрос: что произошло? почему функция func3 вызвалась два раза? и почему произошла ошибка сегментирования, насколько я понимаю такая ошибка возникает только при неправильном обращении с памятью.
В ассемблере это выглядит так(я убрал вывод в поток для краткости, поведение сохраняется):
.file "main.cpp"
.text
.p2align 4
.globl _Z5func1v
.type _Z5func1v, @function
_Z5func1v:
.LFB0:
.cfi_startproc
endbr64
ret
.cfi_endproc
.LFE0:
.size _Z5func1v, .-_Z5func1v
.p2align 4
.globl _Z5func2v
.type _Z5func2v, @function
_Z5func2v:
.LFB5:
.cfi_startproc
endbr64
ret
.cfi_endproc
.LFE5:
.size _Z5func2v, .-_Z5func2v
.section .text.unlikely,"ax",@progbits
.globl _Z5func3v
.type _Z5func3v, @function
_Z5func3:
.LFB2:
.cfi_startproc
endbr64
.cfi_endproc
.LFE2:
.size _Z5func3v, .-_Z5func3v
.globl main
.type main, @function
main:
.LFB3:
.cfi_startproc
endbr64
.cfi_endproc
.LFE3:
.size main, .-main
.ident "GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
Интересно что если скомпилировать без оптимизации то программ отработает корректно.
g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Ответы (1 шт):
Автор решения: AlexGlebe
→ Ссылка
Посмотрел ассемблерный код. Там нет команды ret. И функция продолжает выполнять функцию main. В godbolt зацикливания не произошло.
func3():
sub rsp, 8
mov edx, 5
mov esi, OFFSET FLAT:.LC2
mov edi, OFFSET FLAT:std::cout
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
mov edi, OFFSET FLAT:std::cout
call std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
call func1()
call func2()
main:
sub rsp, 8
call func3()