[UPD] забавный крэш
От: ononim  
Дата: 30.09.21 20:15
Оценка: 18 (7) +1
Linux, libc-2.33, GCC 11.1.0, оптимизация -O2, следующий код падает с SIGSEGV:
#include <string>
#include <iostream>

bool foobar(const std::string &s)
{
    std::string sx = s;
    std::cout << sx << std::endl;
}

int main(int argc, char **argv)
{
    foobar(argv[0]);
    return 0;
}

/home/user/test$ g++ -O2 -std=c++11 ./test.cpp -o ./test && ./test
./test.cpp: In function 'bool foobar(const string&)':
./test.cpp:8:1: warning: no return statement in function returning non-void [-Wreturn-type]
8 | }
| ^
./test
Segmentation fault (core dumped)

.. а если поменять bool foobar на void foobar, или добавить return false, то не падает. Ну подумаешь забыл вернуть bool

С GCC 7.5.0 не падает кстати.

[UPD]
std::string как выяснилось непричем, чисто сишный аналог так же падает, будучи собранным g++:
#include <stdio.h>

bool foobar(const char *s)
{
    printf("foobar(%s)\n", s);
}

int main(int argc, char **argv)
{
    foobar(argv[0]);
    return 0;
}

/home/user/test$ g++ -O2 ./test.c -o ./test && ./test
./test.c: In function 'int foobar(const char*)':
./test.c:6:1: warning: no return statement in function returning non-void [-Wreturn-type]
6 | }
| ^
foobar(./test)
Segmentation fault (core dumped)


а вот gcc -O2 ./test.c -o ./test && ./test — бодрячком

как выяснилось компилятор просто не генерит инструкцию ретурна
0000000000001150 <_Z6foobarPKc>:
    1150:    48 89 fe                 mov    rsi,rdi
    1153:    48 83 ec 08              sub    rsp,0x8
    1157:    48 8d 3d a6 0e 00 00     lea    rdi,[rip+0xea6]        # 2004 <_IO_stdin_used+0x4>
    115e:    31 c0                    xor    eax,eax
    1160:    e8 cb fe ff ff           call   1030 <printf@plt>
    1165:    66 2e 0f 1f 84 00 00 00 00 00     cs nop WORD PTR [rax+rax*1+0x0]
    116f:    90                       nop

0000000000001170 <__libc_csu_init>:
    1170:    f3 0f 1e fa              endbr64 
    1174:    41 57                    push   r15
...

...ну я понимаю конечно что undefined behaviour, но зачем прям сразу начисто ногу отстреливать то
Как много веселых ребят, и все делают велосипед...
Отредактировано 30.09.2021 21:05 ononim . Предыдущая версия . Еще …
Отредактировано 30.09.2021 20:50 ononim . Предыдущая версия .
Отредактировано 30.09.2021 20:47 ononim . Предыдущая версия .
Отредактировано 30.09.2021 20:45 ononim . Предыдущая версия .
Отредактировано 30.09.2021 20:20 ononim . Предыдущая версия .
Отредактировано 30.09.2021 20:19 ononim . Предыдущая версия .
Re: [UPD] забавный крэш
От: σ  
Дата: 30.09.21 23:42
Оценка: 6 (1) +3 :)))
O>как выяснилось компилятор просто не генерит инструкцию ретурна
O>...ну я понимаю конечно что undefined behaviour, но зачем прям сразу начисто ногу отстреливать то

Когда компилятор выкидывает ветки с UB, то всякие поборники "портабельного ассемблера" начинают вопить что компилятор не должен заниматься такой самодеятельнотью, а должен напрямую транслировать программу в ассемблер так, как велел программист.
В данном случае компилятор так и поступил: нет return — не генерируется инструкция. Что, интересно, теперь вопить будут?
Отредактировано 06.10.2021 23:29 σ . Предыдущая версия . Еще …
Отредактировано 30.09.2021 23:43 σ . Предыдущая версия .
Re[2]: [UPD] забавный крэш
От: ononim  
Дата: 01.10.21 13:43
Оценка: +2 -1
O>>.. а если поменять bool foobar на void foobar, или добавить return false, то не падает. Ну подумаешь забыл вернуть bool
MD>Так оно же предупреждение генерит. А далее уж "шо выросло — то выросло".
Предупреждение дело хорошее, но не оправдание. Впрочем по стандарту это UB, а это уже оправдание. Я не то чтоб прошу переделать компиляторы, просто предупреждаю других о новой интересной формы грабле, присущей самым современным трафикам gcc.
А что касается пожеланий, то очевидно компилятор считает что раз нету ретурна — то значит функция — noreturn. Ну положим считает, но в таком случае во-первых можно было в варнинге конкретнее написать о таком умозаключении компилятора, во-вторых хотелось бы чтоб в дебажной версии поведение было аналогичным (сейчас без -O2 — не падает) и в идеале чтоб исполнение не проваливалось в следующую функцию вызывая тонны радости у девелопера, а брякалось на излете — ведь там куча места под нопы отвели, могли бы забить их брекпоинтами.
Как много веселых ребят, и все делают велосипед...
Отредактировано 01.10.2021 13:46 ononim . Предыдущая версия . Еще …
Отредактировано 01.10.2021 13:44 ononim . Предыдущая версия .
Re: [UPD] забавный крэш
От: Умака Кумакаки Ниоткуда  
Дата: 30.09.21 23:21
Оценка:
Здравствуйте, ononim, Вы писали:

я уже и не помню, когда я видел в последний раз проект без
-Werror=return-type
нормально делай — нормально будет
Re[2]: [UPD] забавный крэш
От: flаt  
Дата: 01.10.21 09:23
Оценка:
Не совсем. По умолчанию функции возвращают управление,
чтобы совсем ужж вручную задать поведение, есть `declspec(naked)` и аналоги.
Re: [UPD] забавный крэш
От: Mr.Delphist  
Дата: 01.10.21 11:41
Оценка:
Здравствуйте, ononim, Вы писали:

O>.. а если поменять bool foobar на void foobar, или добавить return false, то не падает. Ну подумаешь забыл вернуть bool


Так оно же предупреждение генерит. А далее уж "шо выросло — то выросло".
Re[3]: [UPD] забавный крэш
От: Alexander G Украина  
Дата: 12.01.22 11:50
Оценка:
Здравствуйте, ononim, Вы писали:

O>хотелось бы чтоб в дебажной версии поведение было аналогичным (сейчас без -O2 — не падает) и в идеале чтоб исполнение не проваливалось в следующую функцию вызывая тонны радости у девелопера, а брякалось на излете — ведь там куча места под нопы отвели, могли бы забить их брекпоинтами.


Думаю, достаточно дельное пожелание, чтобы репортить фичареквест, если такового ещё нет.
Русский военный корабль идёт ко дну!
Re[2]: [UPD] забавный крэш
От: удусекшл  
Дата: 12.01.22 12:05
Оценка:
Здравствуйте, σ, Вы писали:

σ>В данном случае компилятор так и поступил: нет return — не генерируется инструкция. Что, интересно, теперь вопить будут?


return — это вернуть значение. Инструкция для возврата управления в любом случае генерируется. Но, видимо, компилятор решил просто оставить стек в кривом состоянии. Но по уму тогда бы надо ошибку сгенерировать, а не просто варнинг. Варнинг годится, если компилятор всё корректно генерит для возврата значения, но само значение будет неопределённым
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.