Если я столкнулся с старым кодом, который делает if (!this) return;
в приложении, насколько серьезным может быть риск? Это опасная тикающая бомба замедленного действия, которая требует немедленного поиска в приложении и уничтожения усилий, или это скорее напоминает запах кода, который можно спокойно оставить на месте?
Я не планирую писать код, который делает это, конечно. Скорее, я недавно обнаружил что-то в старой библиотеке, используемой многими частями нашего приложения.
Представьте, что класс CLookupThingy
имеет не-виртуальную CThingy *CLookupThingy::Lookup( name )
функцию-член. По-видимому, один из программистов в те дни ковбоев сталкивался со многими авариями, когда NULL CLookupThingy *
передавался из функций, а вместо того, чтобы фиксировать сотни сайтов-звонков, он спокойно фиксировал 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; неизбежно некоторые будут упущены, внедряя новые ошибки, которые случайно появятся в течение следующего года разработки.
Поэтому я склонен оставить его в покое, если это абсолютно необходимо.
Учитывая, что это технически undefined поведение, насколько опасно if (!this)
на практике? Стоит ли человеко-недель труда исправлять, или можно рассчитывать, что MSVC и GCC будут безопасно возвращаться?
Наше приложение компилируется на MSVC и GCC и работает на Windows, Ubuntu и MacOS. Переносимость других платформ не имеет значения. Функция, о которой идет речь, никогда не будет виртуальной.
Изменить: Вид объективного ответа, который я ищу, похож на
- "Текущие версии MSVC и GCC используют ABI, где невиртуальные члены действительно статики с неявным параметром 'this', поэтому они будут безопасно входить в функцию, даже если 'this' равно NULL" или
- "будущая версия GCC изменит ABI, чтобы даже невиртуальные функции требовали загрузки цели ветки из указателя класса" или
- "текущий GCC 4.5 имеет несогласованную ABI, где иногда он компилирует невиртуальные элементы как прямые ветки с неявным параметром, а иногда и указатели функции смещения класса."
Первое означает, что код вонючий, но вряд ли break; второй - это то, что нужно проверить после обновления компилятора; последний требует немедленных действий даже при высокой стоимости.
Ясно, что это скрытая ошибка, ожидающая своего появления, но прямо сейчас я беспокоюсь только об уменьшении риска для наших конкретных компиляторов.