Комментарии 92
В том числе поэтому языки, не имеющие NULL, рулят)
разыменовать любой другой указатель
Ответ почти аналогичный: в том числе поэтому языки с указателями это плохо)
Чтобы обойти статические проверки компилятора, даже придумали для нуля ключевое слово null.
Интересно, можно ли было обойтись без null.
обойтись без null
let obj: Option<MyClass> = get_some_object_if_exists();
match obj {
Some(x) => { println!("Имя объекта: {}", x.getName()) },
None => { println!("Объекта нету") }
}
Без явной проверки на наличие объекта обратиться к нему в Rust никак нельзя, obj.getName()
не скомпилируется, только или match
, или if let
, или obj.unwrap().getName()
, если есть уверенность, что объект действительно есть (а если его таки не окажется, то на unwrap программа упадёт с внятным сообщением об ошибке, а не с неопределённым поведением как в C/C++)
А просто let obj: MyClass = чтототам
будет содержать рабочий объект гарантированно и в таком случае будет можно obj.getName()
Смотрите шире: просто не надо писать на С++ то, что можно писать не на С++. Я Rust не знаю, но приведённый пример вызывает уныние: это что, при каждом обращении к свойству объекта необходимо вручную писать код, что делать, если объекта нет? Извините, но это просто слишком. Если писать код не для спутника или ядерной ракеты, то это просто безумный расход труда на перестраховки.
Зачем при каждом-то
// fn get_some_object_if_exists() -> Option<MyClass> { ... }
let obj: MyClass = match get_some_object_if_exists() {
Some(x) => { x },
None => { println!("Объекта нету"); return; }
};
// Здесь объект уже абсолютно точно есть
println!("{}", obj.getName());
println!("{}", obj.getDate());
println!("{}", obj.getStatus());
println!("{}", obj.getЧтоТоТам());
// ...
Или, как вариант
if let Some(obj) = get_some_object_if_exists() {
println!("{}", obj.getName());
println!("{}", obj.getЧтоТоТам());
// ...
} else {
println!("Объекта нету");
}
Капитан Очевидность замечает, что если объекта нет, то и обращаться к нему нельзя. Причём вы ДОЛЖНЫ проверить, есть объект или нет, вообще на ЛЮБОМ языке программирования, ОСОБЕННО на C/C++ :)
Простейший пример: функция загрузки какого-либо объекта из файла, если файла нет или он повреждён — возвращается NULL. Естественная абстракция.
Без NULL необходимо вводить специальный экземпляр «невалидного объекта», на который после вызова функции следует проверять возвращённое значение. Проверка такая же, только теперь уже анализатор под это не напишешь. Более того, приложение начнёт работать как ни в чём не бывало, если эту проверку пропустить. В итоге этот-то баг как раз и просочится на электростанцию и вылезет через 20 лет, а не будет обнаружен на тестировании.
Разве не так всё?
Так с NULL оно может или падать, или не падать — как повезёт. На тестировании не упадёт, а на атомной станции через 20 лет сложится такая сильно специфическая ситуация, что оно возьмёт да упадёт, кто знает. Или наоборот: на тестировании будет падать и на это будет расчёт (хотя зачем так вообще делать?), а на станции возьмёт и не упадёт.
Языки, в которых эту самую проверку пропустить нельзя, рулят) Специальный экземпляр «невалидного объекта» должен быть таким, чтобы его нельзя было не проверить. Тот пример на Rust, что я кинул выше, подходит и для этого случая с файлом. Анализ там проходит прямо в процессе компиляции и никаких проблем нет и быть не может)
Кстати, за это я не люблю активно пиарившийся тут Go: там проверку пропустить можно (if err != nil
, вот это вот всё), и это считается нормой. В Rust пропустить проверку нельзя — не скомпилируется.
NULL — это не просто ноль, а нулевой указатель.А разве не nullptr, как теперь рекомендуется?
Но принята «конвенция», что в памяти по адресу ноль не может быть объекта/переменной.
Именно поэтому разыменование нулевого указателя (или обращение с полям/методам переменной ссылочного типа) приводит в лучшем случае Null Reference/Pointer Exception, в худшем — к Undefined Behaviour.
В «особых случаях» нулевой адрес является вполне себе валидной штукой — примеры опять же можно найти в гугле.
Под рукой нет Кернигана-Ритчи, но насколько я помню, разыменование указателя, который не содержит адрес объекта того типа, на который ссылается этот указатель, это Undefined Behavior. Ни о каком особом статусе нулевого адреса я не помню. Может просто невнимательно читал.
Все эти фокусы с указателями, разыменовываниями и прочим могут выглядеть как игра с огнем или чем-то более опасным, но если просто оперировать памятью, структурами и массивами, то оно все выглядит вполне естественным. Выделил память, передал в функцию адрес этой памяти, записал по нужному смещению нужное значение. Никакой магии, все на виду.
An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
Теперь я буду знать, что у нулевого адреса и нулевого указателя действительно особый статус, определенный стандартом.
Не совсем так. В стандарте нет требования, чтобы нулевой указатель указывал на нулевой адрес. На нестандартных архитектурах или компиляторах он может указывать, к примеру, на 0xffffffff.
В стандарте нет требования, чтобы нулевые указатели в понимании разных компиляторов совпадали. Если на некоторой платформе все нулевые указатели равны 0xffffffff — это не будет нарушением стандарта.
Так в станарте не сказано, что битовое представление константы 0 и нулевого указателя должно совпадать. Это в коде вы пишите
int xxx = 0
void* ptr = (void*)xxx;
а машина выполняет
if xxx == 0 {
ptr = 0xFFFFFFFF;
}
Никаких противоречий, хоть и непривычно.
Нет, не так. (void*)xxx
будет указателем на нулевой адрес. К нулевому указателю приводится только константа 0.
И выше вам верно отметили, что NULL это необязательно 0, может быть и "-1" (все биты единичные)
Даже в WinAPI, функции, возвращающие хендлы (те же указатели), в качестве невалидного указателя, через одну возвращают то 0, то -1.
Сложность возрастает. Нужно писать больше if для одного и того же, потому что внезапно значение вместо юзернейм пришёл нул. Особенную пикантность добавляет то, что в типизированных языках обычно нет разделение на тип который может принимать нул и тип который не может. Приходится пилить костыли, как это сделано в восьмой яве — Optional. Но эти костыли на то и костыли что спасают только от части проблем.
-Рассмотренные проекты явно не детьми разрабатываются, а ошибки такие допускаются…
-Но не потому что не знают, что это такое, а по невнимательности.
Причина не имеет значения, ключевое слово «допускаются». А главное, попробуйте потом объяснить, что «я просто просмотрел» персоналу ближайшей атомной электростанции :)
С утверждением о языках, не имеющих NULL, категорически согласен :)
Поддерживаемые спецификации языков программирования
ANSI С/С90/С99/С11;
C++98/C++2003/С++11/С++14;
Java 6/7 Language Specification;
PHP 4/5;
С# 5.0.
В общем, кроме Си/C++ никакие языки толком не поддерживаются.
С# 5.0
Абсолютно не актуально, ибо на дворе уже 2017 с C# 7.0
Также как Java 8 и PHP 7 (если уже новых версий не выпустили, я там не слежу особо). Собственно, потому я и выделил эти версии.
Но они и такой поддержки не заявляли. А тут поддержка как бы есть — но на самом деле ее нет.
Кстати, а при чем тут вообще PVS-Studio?
Который, конечно же не оставил без внимания этот нюанс.
if( !pColl ) pColl->SetNextTxtFmtColl( *pDoc->GetTxtCollFromPool( nNxt ));
Термин опечатка. Ведь в показанных примерах явно «дрогнула рука». Впрочем, это не значит, что это не серьезная ошибка. И обнаруживаем мы таких ошибок действительно много (примеры найденных ошибок в открытых проектах: V522, V595, V713). А двойственность в том, что эту ошибку можно назвать и уязвимостью. Думается мне, рано или поздно мы выпустим PVS-Studio для поиска уязвимостей, вообще ничего в нём не меняя, кроме названия диагностик и документации. :)
Чему вы так радуетесь? Вы их прайс-то видели?
который корректно собирается в Visual C++


Шаги такие:
- запустить утилиту CppConfMonitor.exe
- пересобрать проект в Visual Studio
- остановить утилиту, введя «s» в ее консоли
- утилита сформирует архив, который нужно загрузить в AppChecker
Объясняю при чем тут прайс. После выхода версии PVS-Studio под Linux а также появления бесплатной лиценции со своеобразными, но все же выполнимыми, условиями, у нас осталась всего одна причина ненавидеть PVS-Studio — их секретный прайс.
И когда человек пришел сюда и написал в комментариях: "Долой PVS-Studio! Да здравствует конкуренция на Хабре." — мне и стало интересно, видел ли он ваш прайс. Я вот, к слову, его не нашел.
Результат: 2 351 упоминание в коде.
Простите, но где это выбирать и переключать?
UPD: там не "настройки не сохраняются", а нельзя выполнить поиск по всем открытым репозиториям по прямой ссылке. Надо обязательно либо вводить запрос вручную, либо после перехода по ссылке поменять любую настройку. И еще надо быть залогиненым — анонимам искать по всем репозиториям нельзя.
(удалено)
Ряд алгоритмов, используемых в AppChecker, покрывается следующим патентом:
https://npo-echelon.ru/upload/iblock/7d0/7d01385cccfddcb4eb4c925db3fc3b7a.png
Рад за отечественную разработку, честно.
Компания Эшелон специализируется на проведении работ в системах сертификации ФСТЭК, МО, ФСБ. Для проведения этих работ много лет назад разработано средство анализа АК-ВС, осуществляющее ряд исследований по руководящему документу ФСТЭК по контролю наличия недекларированных возможностей. Те, кто с этим средством имел несчастье соприкасаться, знаком с его качеством реализации и функционирования.
В прошлом году был утверждён ГОСТ, разработанный компанией Эшелон, определяющий процесс безопасной разработки ПО. ГОСТ будет обязателен для применения компаниями, которые работают на рынке сертифицируемых решений. Это светлое будущее различных систем сертификации, в котором декларируется необходимость поиска программных дефектов (уязвимостей). Вот для этого и разрабатывается AppChecker. Ни разработчикам, ни потребителям, ни исследователям, ни экспертам не интересно качество реализации и функционирования средства анализа, всем нужна заветная бумажка — сертификат. Есть бумажка — ПО надёжно и безопасно.
По поводу качества первой версии нашего продукта АК-ВС: качество – характеристика относительная и, если решили о ней поговорить, то давайте сравнивать с другими аналогичными решениями, а потом уже выплескивать эмоции. Продукт, как вам известно, не единственный на рынке, также никто не мешает вам разработать собственный инструмент анализа.
Правда, проводить тестирование лучше уже АК-ВС 2, который уже пару лет как представлен на рынке. Если у вас появятся конкретные предложения по улучшению нашего продукта, будем очень признательны.
Спасибо, что вспомнили ГОСТ Р 56939-2016. В его разработке приняло участие 105 компаний и было учтено более 300 замечаний (в том числе и от вашей). Нам о планах сделать его обязательным ничего неизвестно, но мы бы порадовались, так как вложили в ГОСТ массу интеллектуальных усилий: обратите внимание, что он не является переводом западного, а разработан специально под наши реалии. Если его читать внимательно, то можно заметить, что помимо статического анализа кода, реализованного в AppChecker, предусматривается и динамический анализ, и fuzzy-тестирование, и тестирование на проникновение и многие другие меры.
Александр, предлагаем вам, как эксперту скачать AppChecker и попробовать его в деле, и поделиться впечатлением на страницах Хабра, а мы вам подарим наш легендарный перекидной календарь!
не солидно выглядит такое распространение софта от фирмы с профилем по ИБ.
Не эксперт, но заинтригован… что в вашем календаре легендарного — он очень старый… за какой год?
Вас оправдывает то, что аналогичные решения написаны такими же безразличными к результату разработчиками? Да и какие это решения, Аист-С? Все, кто работает в отрасли сертификации, прекрасно знает как работает АК-ВС и что большая удача найти хоть какие-то исходники, на которых он отработает без единого сбоя.
АК-ВС за последние годы стал стандартом де-факто в отрасли сертификации, новые лаборатории покупают у вас продукт, отправляют в ваш учебный центр своих сотрудников, которые после прохождения обучения начинают считают, что раз средство разрешено к применению ФСТЭКом, то это автоматически решает все проблемы. Старый добрый принцип — есть бумажка, значит всё защищено и надёжно. В итоге у среднего специалиста в отрасли сертификации долгие годы было убеждение, что надо просто запустить АК-ВС, скормить ему исходники, сгенерировать протоколы и отправить их для проведения экспертизы, где в их содержимое редко кто будет вчитываться на предмет корректности проведённых работы. Вот и вся работа, вся сертификация на НДВ.
АК-ВС 2 пару лет представлен на рынке, но при этом работает также некорректно (но чуть лучше, чем АК-ВС). При этом, по старой доброй традиции, это никому не мешает: ни вам — его продавать, ни регуляторам — его разрешать к применению, ни лабораториям — его непосредственно применять.
Первая редакция ГОСТ представляла собой РД НДВ в новой обёртке. Утверждённая редакция является просто учётом тех замечаний, о которых вы упомянули. Если я правильно помню (это легко уточнить), то те виды исследований, которые вы перечислили, появились именно по результатам устранения замечаний.
npoechelon, я неоднократно пробовал в деле и АК-ВС, и АК-ВС 2. Вы думаете, что у меня ещё осталась надежда, что у вашей компании есть мотивация делать качественные продукты? Единственная ваша цель — не допустить распространения в отрасли сертификации PVS-Studio и средств анализа путём формального выполнения требования использования статического анализа. В качестве вы не заинтересованы.
По вашему тексту можно изучать методы геббельсовской пропаганды. Здесь есть и явная ложь («появились именно по результатам устранения замечаний»), и попытки манипулировать («Все, кто работает… прекрасно знает», «Старый добрый принцип…»), и отсутствие конкретики («работает также некорректно, но чуть лучше»), и попытки сталкивать с третьей стороной («ваша цель — не допустить распространения в отрасли сертификации…»), ну и, конечно, перевод на параллельные темы и масса эмоций (в основном обиды). Короче, характерно выделяющийся профиль.
Так как дискуссия перестает быть конструктивной, этот ответ вам будет заключительным.
Теперь по пунктам.
Относительно ГОСТ Р 56939-2016, который вы связали с обсуждаемой темой.
По поводу исследований, которые с ваших слов появились после замечаний, вот первый вариант стандарта, в котором они все есть, так как были изначально: http://docs.cntd.ru/document/1200113247
Cмотреть нужно 13-16 стр. asasasdd, ЛГАТЬ – это очень плохо.
Ликбез. Разумеется, ГОСТ изначально не был копией РД НДВ и не задумывался таковым. Извините, ну уж даже не знать, что упоминаемый статический анализ в РД и в ГОСТ – это абсолютно разные понятия?! Да уж.
Идея РД НДВ в декомпозиционном подходе к разбору структуры текста программы (там вопросы безопасности косвенно возникают лишь тогда, когда речь идет о защите гостайны уровня аж СС!). Это поймет любой начинающий программист.
ГОСТ Р 56939-2016 – это (для справки) организационный стандарт, который в том числе включает в себя совокупность мер, которые может обоснованно принять разработчик ПО с целью повышения безопасности программного изделия в рамках именно его жизненного цикла! Здесь, пардон, преследуются другие цели: разработчики стремятся минимизировать риски появления ошибок безопасности, уязвимостей, угроз (связанных их наличием) и т.п. Иные и задачи, и предметная область, и методическая база.
Относительно АК-ВС, который вы подтянули к обсуждаемой теме:
Есть старый анекдот:
— Таки мне Каррузо не понравился: каатавит, гнусавит, в ноты не попадает…
— Вы были на концерте Карузо?
— Нет, мне дгуг по телефону напел.
asasasdd, вы легально используете АК-ВС 2.0 на своем месте работы, и у вас есть конкретные замечания по целевой работе этого продукта? Вы о них сообщили в техподдержку? Разработчики не отреагировали? Номера ваших обращений в техподдержку? Все, как в анекдоте.
Мы признательны всем за конструктивные конкретные замечания и предложения по улучшению продукта, чему и посвящен данный пост.
User Interface: красиво:) Запускаешь серверную часть, идешь в браузер — создаешь проект. И тут — неудобство:
Для С/C++ проектов требуется дополнительная конфигурация.Я понимаю, почему это сделано, но запускать утилиту, которая мониторит системные вызовы — не всегда удобно.
На большом проекте, использующем Qt и сторонние библиотеки, утилита сдохла. bad_alloc и падение без каких-либо полезных результатов. Уже минус, т.к. проверять планировал именно его.
Открыт древний и большой проект, не использующий ничего и написанный на Си с классами:)
Продукт нашел всего 4 дефекта трех типов, которые, признаюсь, действительно выглядят странно:
- присвоение переменной самой себе
tmp = tmp;
- всегда истинное выражение
if ( arr[i]!='+' || arr[i]!=' ' )
- неконтролируемая рекурсия
ISuperStringStream& MySuperStringStream::operator<<(signed char v) { return operator<<((char)v) ; }
При этом параллельно работал CppCheck, который одних только ошибок нашел 37 штук, варнинги и прочие стилистические сообщения я отключил. При этом в коде есть вещи, которые явно указывают на ошибку:
void nps::MyClassEvent::getTextData(MyElement& el) const
{
el.doSmth();
MyAttributes* attr = new MyAttributes() ;
attr->insert("t0") ;
}
У меня есть подозрение, что AppChecker анализирует не все файлы и файл с проектом сформировался криво, но как это быстро проверить и исправить, я не знаю.
Возможно, я что-то делаю не так, однако для быстрой проверки CppCheck и прочие Clang Static Analyzer'ы лично мне подходят удобнее.
Я допускаю, что ваш продукт можно правильно настроить и он будет работать превосходно, но, например, ручное формирование и загрузка специально сохраненного файла — как-то это долго и лениво.
Проверял я на standalone-приложении. Отпишу кратко впечатления от первого запуска. При первом запуске увидел отличную

Проверил на двух машинах, проблема воспроизводится. Но на дальнейшую работоспособность никак не влияет, кажется.
Отличие от AppChecker'а — наличие удобного standalone-приложения: тоже приходится запускать мониторинг вызовов компилятора, но делается это из нормального графического интерфейса, а не из консольной утилиты. Результаты работа мониторинга никуда передавать не надо, они сразу отображаются в окне приложения PVS-Studio Standalone.
Проект с Qt и сторонними библиотеками вполне себе проверился. Ничего критичного там, к счастью, не нашлось, но пару членов класса мы инициализировать забываем:(
Древний проект на Си с классами тоже прошел сканирование: 120 ошибок высокой важности, 168 — средней, 870 — низкой. Примеры ошибок:
V570 The 'Parabola' variable is assigned to itself. SomeFileName.cpp 287
Parabola =Parabola ;
V522 Dereferencing of the null pointer 'SetterGetter' might take place. OtherFileName.cpp 305
if ( SetterGetter==0 )
{
SetterGetter->set(false) ;
}
При проверке старых проектов увидел странные дефекты:
V546 Member of a class is initialized by itself: 'd(d)'. qsharedpointer_impl.h 561
inline QWeakPointer(X *ptr) : d(ptr ? d->getAndRef(ptr) : 0), value(ptr)
{ }
V672 There is probably no need in creating the new 'stream' variable here. One of the function's arguments possesses the same name and this argument is a reference. Check lines: 8, 17. entityhelper.cpp 17
void PrintEntityParams(QDebug& stream, const paramsMap_t& parameters) // 8 строка
{
if (parameters.isEmpty())
{
return;
}
if (!SingletonDataProvider::GetInstance().IsInitialized())
{
LOG_ERROR("SingletonDataProviderне инициализирован"); // 17 строка
return;
}
const SingletonDataProviderне& storage = SingletonDataProviderне::GetInstance();
stream << ". Параметры:";
for (paramsMap_t::const_iterator it = parameters.constBegin(); it != parameters.constEnd(); ++it)
{
stream << storage.GetAttributeName(it.key()) << '='
<< SomeHelper::GetInstance().ToString(it.value()) << ';';
}
}
Выяснилось, что макрос LOG_ERROR при разворачивании создает переменную с названием 'stream'. Если я правильно помню описание работы PVS-Studio на хабре, то с такими ложными срабатываниями можно бороться. В рамках быстрого ознакомления этого делать не стал, нет необходимости.У PVS-Studio Standalone в контекстном меню найденных ошибок есть пункт «Add TODO comments for selected messages» — удобная вещь для накопления технического долга:)
Оказалось, что легко и даже приятно исключать директории из сканирования — в частности, ошибки в Qt я предпочел больше не искать.
Ну и на закуску я решил проверить анализаторы на
bool CheckPointer(int value)
{
int* intPtr(new int(value));
std::cout << std::endl << *intPtr << std::endl;
return true;
}
class A {
int x;
public:
void bar() {
std::cout << x << "Test!\n";
}
};
int main()
{
CheckPointer(5);
A* a;
a->bar();
return 0;
}
PVS-Studio нашла две ошибки:
- V773 The function was exited without releasing the 'intPtr' pointer. A memory leak is possible. main.cpp 224
- V614 Uninitialized pointer 'a' used. main.cpp 238
AppChecker: В проекте не обнаружены потенциальные уязвимости и дефекты
CppCheck тоже говорит, что ошибок не найдено.
В целом — AppChecker'у есть куда расти как в части удобства, так и в части функциональности анализа. Пока что складывается ощущение, что сделать хотели много (и отчеты, и сравнение результатов сканирования), а получилось — не очень. Но я уверен, что разработчики компании «Эшелон» быстро исправятся и смогут составить достойную конкуренцию на рынке статических анализаторов и в статьях хабра!
И еще пару слов: наша небольшая команда разработчиков использует обязательное ревью всего кода, часть кода покрыта тестами, флаги компилятора включены по максимуму. И это все равно не избавляет нас от ошибок в коде — при запуске я был неприятно удивлен количеством срабатываний анализатора. Я думаю, что и синтаксический анализ не сможет полностью избавить от ошибок, но уменьшить их количество он сможет наверняка. Поэтому — рекомендую.
Касательно ложного срабатывания. В PVS-Studio есть множество механизмов для их подавления. В данном случае, лучше всего написать комментарий:
//-V:LOG_ERROR:V672
Комментарий рационально написать рядом с объявлением макроса. Тогда комментарий будет воздействовать на весь код, где используется этот макрос. Есть и другие способы. Подробности можно посмотреть в документации.
Ещё раз спасибо.
P.S. Да, если кому-то интересны графики и т.п., напоминаю, что PVS-Studio умеет интегрироваться с SonarQube.
На вскидку, предлагаю взять проект WinMerge. Но не потому, что он очень забагован :). Просто проект небольшой и должен относительно легко проверяться (правда не знаю, что делать с Clang). Мы про него уже пару раз писали (в 2010 и 2012 году). Но только надо брать старую версию проекта (скажем конца 2009 года), когда до него ещё не добрался ни PVS-Studio, ни Cppcheck.
Что ещё… Вот есть такой проект Torque2D. Я его пару месяцев назад быстренько проверил, увидел, что есть ошибки, но не добрался до полноценной проверки и написания статьи. Можно на нём попробовать.
Вот только PVS-Studio умеет запускаться по-разному, а AppChecker — только через одно место.
Насколько я понимаю, им тоже придется запустить сборку проекта, чтобы гарантировать соответствие исходников и бинарных файлов. Или там другие продукты используются?
Относительно результатов тестов, то похоже действительно проанализировались не все исходники, поскольку те дефекты, которые нашел pvs и о которых Вы пишете в своем комментарии, AppChecker также обнаруживает)
В частности:
V570 The 'Parabola' variable is assigned to itself. SomeFileName.cpp 287
Parabola =Parabola ;
Это тот же тип дефекта, что и нашелся у Вас:
присвоение переменной самой себе
tmp = tmp;
Относительно V522 Dereferencing of the null pointer 'SetterGetter' might take place. OtherFileName.cpp 305
if ( SetterGetter==0 )
{
SetterGetter->set(false) ;
}
об этом типе дефекта собственно сама наша статья) было бы подозрительно, если бы мы писали о таком дефекте и при этом его не обнаруживали)
Я работаю из под QtCreator, pro-файл имеет
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp
Собирается MinGw, версия Qt: 4.6.2
И CppCheck, и PVS-Studio на нем отработали достойно, а AppChecker почему-то ничего не нашел. Хотя в логах разбор cpp-файла присутствовал.
Спрашиваю это потому, что остальные проекты собираются схожим образом, и без примера нет смысла говорить о проверке реального кода.
Ответили Вам на этот вопрос в другой теме: https://habrahabr.ru/company/echelon/blog/320398/#comment_10038854
Обнаружение в коде дефекта «разыменование нулевого указателя»