Следующее является бессмысленным, но компилируется с помощью g++ -Wall -Wextra -Werror -Winit-self
(я тестировал GCC 4.7.2 и 4.9.0):
#include <iostream>
#include <string>
int main()
{
for (int ii = 0; ii < 1; ++ii)
{
const std::string& str = str; // !!
std::cout << str << std::endl;
}
}
Линия, отмеченная !!
, приводит к поведению undefined, но GCC не диагностируется. Однако, комментируя строку for
, GCC жалуется:
error: ‘str’ is used uninitialized in this function [-Werror=uninitialized]
Я хотел бы знать: почему GCC так легко обмануть здесь? Когда код не находится в цикле, GCC знает, что это неправильно. Но поместите тот же код в простой цикл, и GCC больше не понимает. Это беспокоит меня, потому что мы очень много полагаемся на компилятор, чтобы уведомить нас, когда мы делаем глупые ошибки на С++, но это не удается для кажущегося тривиального случая.
Бонусные мелочи:
- Если вы измените оптимизацию
std::string
наint
и, GCC будет диагностировать ошибку даже в цикле. - Если вы создадите сломанный код с помощью
-O3
, GCC буквально вызывает функцию вставки ostream с нулевым указателем для строкового аргумента. Если вы считаете, что находитесь в безопасности от нулевых ссылок, если вы не делаете никаких небезопасных кастингов, подумайте еще раз.
Я зарегистрировал ошибку GCC для этого: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63203 - Мне все равно хотелось бы лучше понять, что пошло не так, и как это может повлиять надежность аналогичной диагностики.