Если я сталкиваюсь со старым кодом, который содержит if (!this) return;
в приложении, насколько серьезен этот риск?Это опасная бомба замедленного действия, требующая немедленного поиска и уничтожения всего приложения, или это больше похоже на запах кода, который можно спокойно оставить на месте?
Я не планирую писать код, который делает это, конечно.Скорее я недавно обнаружил кое-что в старой базовой библиотеке, используемой многими частями нашего приложения.
Представьте, что класс CLookupThingy
имеет не виртуальную CThingy *CLookupThingy::Lookup( name )
функцию-член.Видимо, один из программистов в те ковбойские времена сталкивался со многими сбоями, когда NULL CLookupThingy *
s передавался из функций, и вместо того, чтобы исправлять сотни сайтов вызовов, он спокойно исправлял Lookup ():
CThingy *CLookupThingy::Lookup( name )
{
if (!this)
{
return NULL;
}
// else do the lookup code...
}
// now the above can be used like
CLookupThingy *GetLookup()
{
if (notReady()) return NULL;
// else etc...
}
CThingy *pFoo = GetLookup()->Lookup( "foo" ); // will set pFoo to NULL without crashing
Я обнаружил этот драгоценный камень ранее на этой неделе, но сейчас у меня возникает вопрос, должен ли я его починить.Это основная библиотека, используемая всеми нашими приложениями.Некоторые из этих приложений уже были отправлены миллионам клиентов, и, похоже, они работают нормально;в этом коде нет сбоев или других ошибок.Удаление if !this
в функции поиска будет означать исправление тысяч сайтов вызовов, которые потенциально проходят NULL;неизбежно некоторые будут пропущены, что приведет к появлению новых ошибок, которые будут появляться случайным образом в течение следующего года разработки.
Так что я склонен оставить это в покое, если в этом нет крайней необходимости.
Учитывая, что это технически неопределенное поведение, насколько опасно if (!this)
на практике?Стоит ли исправлять трудозатраты в несколько человеко-недель или можно рассчитывать на MSVC и GCC для безопасного возвращения?
Наше приложение компилируется в MSVC и GCC и работает в Windows, Ubuntu и MacOS.Переносимость на другие платформы не имеет значения.Данная функция гарантированно никогда не будет виртуальной.
Редактировать: Вид объективного ответа, который я ищу, выглядит примерно так:
- "Текущие версииMSVC и GCC используют ABI, где не виртуальные члены действительно статичны с неявным параметром «this», поэтому они будут безопасно переходить в функцию, даже если «this» имеет значение NULL »или
- » в следующей версии GCCизмените ABI так, чтобы даже не виртуальные функции требовали загрузки цели ветвления из указателя класса «или
- », текущий GCC 4.5 имеет несовместимый ABI, где иногда он компилирует не виртуальные члены как прямые ветви с неявным параметром, а иногдав качестве указателей на функции смещения класса. "
Первое означает, что код вонючий, но вряд ли сломается;второе - что-то проверить после обновления компилятора;последнее требует немедленных действий даже при высоких затратах.
Очевидно, что это скрытая ошибка, которая должна произойти, но сейчас меня интересует только снижение риска для наших конкретных компиляторов.