Привет, Codeforces
Вчера, на 366-ом раунде мой друг Birjik столкнулся со странной проблемой. Его правильный код получал ошибку исполнения на примерах.
Взгляните на следующие коды:
Runtime error
Accepted
Вы можете заметить, что код с RE имеет такие строки:
ios_base::sync_with_stdio(0);
cin.tie(0);
Странно, не так ли?
Насколько я понял, это случается поскольку в коде имеется массив с названием "read".
Переименование массива решает эту проблему.
Вкратце, использование ios_base / cin.tie получает ошибку исполнения если мы имеем переменную с названием "read".
Будьте внимательны!
Минимально воспроизводящийся пример
Сборка:
g++ -o main main.cpp -fsanitize=address
cin/cout — зло
глобальные переменные — зло
looks like everyone is mad at you for resigning your job :D
Переменную write тоже нельзя использовать. И да, под MS C++ все нормально.
http://www.gdsw.at/languages/c/programming-bbrown/c_075.htm
В C и C++ есть функции
int read
int write
. Возможно из-за глобальной переменной с таким же именем и типом происходит конфликт в синхронизации?Да, похоже на правду. Название символа как для стандартной функции
так и для глобальной переменной
read
одинаково —read
. При компоновке программы адрес переменной подставляется туда, где должна была быть вызвана одноимённая функция. Попытка вызова переменной как функции приводит к ошибке.Вот как это выглядит в отладчике:
Адрес переменной совпадает:
а манглинг не должен от этого спасать?
read()
— это C-функция, аread
— это глобальная переменная. Поэтому их имена не подвержены манглингу.https://mentorembedded.github.io/cxx-abi/abi.html#mangling-structure:
Спасибо, про extern "C"-функции знал, а вот про глобальные переменные нет.
Workarounds: mark the variable static, put it into an anonymous namespace, put it into a named namespace/class, or don't use global variables.