Я хотел бы знать, возможно ли обнаружить delete
ошибку, прокомментированную ниже во время компиляции? Особенно мне хотелось бы услышать о компиляторе g ++.
ClassTypeA *abc_ptr = new ClassTypeA[100];
abc_ptr[10].data_ = 1;
delete abc_ptr; // error, should be delete []
c++
compiler
error-detection
SebGR
источник
источник
std::unique_ptr<ClassTypeA[]>
и тогда вам не нужно.Ответы:
Как правило, компилятор не может обнаружить такие ошибки. Пример: предположим, что конструктор для некоторого класса выделяет некоторый элемент данных, используя
new TypeName[]
, но деструктор ошибочно используетdelete
вместоdelete[]
. Если конструктор и деструктор определены в отдельных единицах компиляции, как компилятор должен знать при компиляции файла, который определяет деструктор, что использование несовместимо с тем, что используется в отдельно скомпилированном файле, который определяет конструктор?Что касается компиляторов GNU, это не так. Как отмечено выше, это не может сделать это в общем случае. Компилятору не нужно обнаруживать такие несоответствующие новые / удалять ошибки, потому что это неопределенное поведение. UB - это карта компилятора, выпущенная «без выхода из тюрьмы».
Такие инструменты, как valgrind, могут и обнаруживают такие новые / удаляемые несоответствия, но делают это во время выполнения. Может существовать инструмент статического анализа, который просматривает все исходные файлы, которые в конечном итоге будут скомпилированы, чтобы сформировать исполняемый файл, но я не знаю ни одного такого инструмента статического анализа, который бы обнаруживал подобные ошибки.
источник
Вы можете использовать соответствующие классы RAII для
delete
. Это единственный безопасный способ сделать это, и эта ошибка - лишь одна из очень, очень многих, с которыми вы столкнетесь, называяdelete
себя.Всегда используйте классы для управления динамическими ресурсами времени жизни, и система типов обеспечит правильное уничтожение ресурсов.
Изменить: «Что если вы проверяете код и не можете его изменить?» Вы трахались
источник
Эта конкретная ошибка - да. Нет Этот вид ошибки вообще: к сожалению, нет! Это предполагает прогнозирование потока выполнения без его фактического выполнения, а это невозможно для произвольных программ. (Вот почему большинство компиляторов даже не пытаются обнаружить простые случаи, подобные вашему примеру.)
Поэтому ответ DeadMG является подходящим: не пытайтесь сделать это правильно, обращая внимание - человеческое внимание подвержено ошибкам. Используйте языковые средства и пусть компьютер обратит внимание.
источник
ClassTypeA*
поэтому вы можете вставить строку между новым и удалить.if ( rand() % 2 == 1 ) abc_ptr = new ClassTypeA;
Ничто в статической системе типов не показывает,abc_ptr
указывает ли массив или динамический объект или частично на другой объект или массив.abc_ptr
, в противном случае, как она могла бы освободить необходимый объем памяти? Таким образом, среда выполнения знает, сколько объектов должно быть освобождено.Тривиальный случай, который вы показываете, может быть обнаружен во время компиляции, потому что создание экземпляров и уничтожение объекта находятся в одной и той же области видимости. Как правило, удаление находится не в той же области или даже в том же исходном файле, что и экземпляр. И тип указателя C ++ не несет информацию о том, ссылается ли он на отдельный объект своего типа или массив, не говоря уже о схеме размещения. Таким образом, невозможно диагностировать это во время компиляции вообще.
Почему бы не диагностировать возможные случаи?
В C ++ уже есть инструменты для борьбы с утечкой динамических ресурсов, которые привязаны к областям действия, а именно, умные указатели и массивы более высокого уровня (
std::vector
).Даже если вы используете правильный
delete
вкус, ваш код все равно не является безопасным для исключений. Если код междуnew[]
иdelete[]
завершается динамическим завершением, удаление никогда не выполняется.Что касается обнаружения во время выполнения,
Valgrind
инструмент хорошо выполняет обнаружение этого во время выполнения. Часы:Конечно, Valgrind работает не на всех платформах, и не всегда возможно или невозможно воспроизвести все ситуации во время выполнения с помощью инструмента.
источник
Некоторые тривиальные примеры обнаружения во время компиляции / статического анализа:
На хосте RHEL7 с
cppcheck 1.77 and 1.49
http://cppcheck.sourceforge.net/
С
clang++ 3.7.1
на RHEL7Clang Static Analyzer также может определять, когда
std::unique_ptr
он не пройден<char[]>
https://clang-analyzer.llvm.org/
Обновление ниже со ссылкой на работу, которая добавила это в clang, тесты и одну найденную ошибку.
Это было добавлено в clang с reviews.llvm.org/D4661 - «Обнаружить несоответствие« новых »и« удалить »использования» .
Тесты находятся в тесте / Анализ / MismatchedDeallocator-checker-test.mm
Я нашел эту открытую ошибку - bugs.llvm.org/show_bug.cgi?id=24819
источник