#новичкам
Спасибо, @Ivaneo, за любезно предоставленный примерчик в рамках рубрики #ЧЗХ.
Дан простой кусок кода:
#include <array>
#include <cstring>
#include <iostream>
int main(int argc, char *argv[]) {
const char *string{nullptr};
std::size_t length{0};
if (const bool thisIsFalse = argc > 100000;
thisIsFalse) {
string = "ABC";
length = 3;
}
std::array<char, 128> buffer;
std::memcpy(buffer.data(), string, length);
if (string == nullptr) {
std::cout
<< "String is null, so cancel the launch.\n";
} else {
std::cout << "String is not null, so launch the "
"missiles!\n";
}
}
Единственный вопрос: что выведется на экран при запуске программы без аргументов?
Подумайте несколько секунд.
"Да все очевидно же. string не меняется, поэтому сообщение об этом и выведется на экран".
Но мы же на плюсах пишем, тут невозможное становится возможным.
Например, при компиляции на gcc на О3 оптимизациях выводится
String is not null, so launch the missiles!"WAT? Где пруфы?"
А вот они.
Виновато конечно во всем ненавистное UB. Все грязные тряпки кидайте в него.
По стандарту, если в memcpy передать нулевой указатель, то поведение неопределено. Может случиться все, что угодно.
Это может произойти, только если количество аргументов запуска программы меньше 100000. То есть одна ветка приводит к UB, а вторая нет. И на основании этого gcc делает вывод, что порченная ветвь кода никогда не должна выполняться (так как UB означает, что поведение программы не определено, то компилятор может предполагать, что UB не должно происходить) и просто выкидывает эту ветку из ассемблера.
Уберите условие, либо memcpy, то вывод будет ожидаемым. Либо UB не будет, либо эвристики компилятора по-другому заработают.
Пишите качественный и безопасный код, чтобы не было таких неожиданностей.
Be safe. Stay cool.
#cppcore