Помощь в предотвращении всегда утверждает …!

Это было некоторое время, так как я работал в c/c ++, но IIRC, тот же ярлык может использоваться для массивов также.

7
задан fbrereto 4 December 2009 в 00:49
поделиться

10 ответов

На самом деле я не совсем понимаю, в чем проблема. Утверждения обходятся дорого только в том случае, если они срабатывают, что в любом случае нормально, поскольку сейчас вы находитесь в исключительной ситуации.

assert включен только в отладочных сборках, поэтому используйте сборку выпуска сторонней библиотеки. Но на самом деле утверждения не должны происходить каждый момент.

14
ответ дан 6 December 2019 в 06:50
поделиться

Это может быть удобно для улучшения встроенного средства утверждения (для обеспечения трассировки стека, дампа ядра, кто знает). В этом случае, если у вас возникли проблемы с тем, чтобы заставить разработчиков следовать тем стандартам, которые у вас есть (например, «вместо assert () используйте SUPER_ASSERT () » или что-то еще), вы можете просто поместите свой собственный заголовок assert.h в путь включения перед каталогом заголовков времени выполнения компилятора.

Это в значительной степени гарантирует, что любой, кто использует стандартный макрос assert () , получит ошибку компилятора или получит ваши функции утверждения (в зависимости от того, что у вас есть assert.h заголовок делать).

2
ответ дан 6 December 2019 в 06:50
поделиться

Это будет зависеть (по крайней мере частично) от того, что вы меняете. Предполагая, что вы не против того, чтобы он распечатал свое обычное сообщение и в основном хотите избавиться от него, вызывая abort () , вы можете оставить только assert () , а вместо этого определение вашей собственной версии abort () .

Теоретически это не переносимо, но на самом деле abort () является довольно нормальной функцией в стандарте библиотека, и если вы вместо этого свяжете свою собственную, вы получите ее поведение. Иногда (особенно некоторым компоновщикам Microsoft) вам нужно немного поработать, чтобы заставить компоновщик сотрудничать в замене их abort () на ваш, но это редко бывает очень сложно.

2
ответ дан 6 December 2019 в 06:50
поделиться

Я думаю, что вопрос верен.

Мое собственное утверждение при срабатывании расширяется до asm ("int3"), что эквивалентно точке останова. Я также обнаружил, что это гораздо более полезно для отладки, чем простое завершение.

Я просто назвал это «ASSERT ()» вместо обычного «assert ()» и вообще отказался от использования assert ().

2
ответ дан 6 December 2019 в 06:50
поделиться

Самый очевидный подход - дать вашей собственной версии assert свое собственное имя, немного отличается от assert () . Затем вы можете искать в тексте, просматривать сообщения компоновщика и т. Д., для буквальной строки "_assert", и вы знаете, что у вас есть проблема, когда вы ее видите.

В моем собственном коде я всегда использую Assert () , который расширяется до моей собственной функции, выполняющей утверждение или расширяется до ((void) 0) для сборки выпуска. Компилятор превратит выражение ((void) 0) в ничто, но оно все равно будет считаться выражением. Таким образом,

Assert(3 == x);

превратится в

((void)0);

, и точка с запятой имеет место, где нужно идти.

Между прочим, я когда-то работал над приложением с графическим интерфейсом пользователя, где утверждение было специальным модальным всплывающим диалоговым окном графического интерфейса. У вас было три варианта: игнорировать, игнорировать навсегда или прервать. Ignore проигнорирует assert и продолжит работу. «Игнорировать навсегда» установит флаг, и пока вы не перезапустите программу в отладчике, это assert больше не будет срабатывать. Разрыв позволит утверждению проникнуть в отладчик.

Я не помню, как они гарантировали, что каждое утверждение имеет свой собственный флаг. Может быть, когда вы писали вызов Assert (), вам нужно было указать уникальное целое число? Было бы хорошо, если бы это было более автоматическим, чем это. Я почти уверен, что на самом деле имплантация была битовой векторной, и она установит бит, если вы выберете игнорировать навсегда.

1
ответ дан 6 December 2019 в 06:50
поделиться

Думаю, ваш вопрос абсолютно верен. Если вы реализовали собственную обработку ошибок, вам может потребоваться:

  1. Всегда запускать утверждения даже в сборках релизов.
  2. Реализовать более качественные отчеты об ошибках в случае срабатывания триггеров утверждения. Вы можете отправлять отчеты об ошибках или записывать в файлы журналов.

При этом я не вижу решения, которое всегда работает.

  • Если вам повезет, сторонние библиотеки используют макросы ASSERT, которые вы можете переопределите себя до тех пор, пока файл, определяющий этот макрос, имеет какое-то положение #pragma once или #ifndef __HEADERFILE_H__ #define __HEADERFILE_H __ против множественного включения. Включите файл заголовка отдельно, переопределите ASSERT, и все будет хорошо.

  • Если они напрямую включают assert.h или cassert, вы можете исправить только код, я думаю. Внесите минимальные изменения в код, сохраните изменения как файлы исправлений и при обновлении библиотеки надейтесь, что исправления все еще работают. Добавьте исправления в систему контроля версий.

Если это не сработает, подумайте еще раз, если вам действительно нужны внутренние утверждения в сторонних библиотеках. Только сборки релиза корабля, это избавляет от утверждений и добавляет свои АССЕРТЫ для проверки правильности внутри вашего кода. Проверяйте правильность возвращаемых значений. Если такой ASSERT запускается, вы все равно можете погрузиться в сторонний код, чтобы узнать, что вызвало проблему.

и добавьте свои ASSERT для проверки правильности внутри вашего кода. Проверяйте правильность возвращаемых значений. Если такой ASSERT запускается, вы все равно можете погрузиться в сторонний код, чтобы узнать, что вызвало проблему.

и добавьте свои ASSERT для проверки правильности внутри вашего кода. Проверяйте правильность возвращаемых значений. Если такой запрос ASSERT запускается, вы все равно можете погрузиться в сторонний код, чтобы узнать, что вызвало проблему.

2
ответ дан 6 December 2019 в 06:50
поделиться

Кажется, вы упускаете из виду тот факт, что сторонний код, скорее всего, написан с учетом «стандартного» assert поведения. Т.е. код ожидает, что программа завершится при неудачном подтверждении. Код, следующий за утверждением, обычно не может и не будет работать правильно, если заявленное условие нарушено. В 99 случаях из 100 это вообще не сработает. В 99 случаях из 100 он просто выйдет из строя, т.е. программа все равно завершится.

Наивно полагать, что, переопределив поведение assert в стороннем коде, вы каким-то образом продлите жизнь программе. в лучшем случае.

1
ответ дан 6 December 2019 в 06:50
поделиться

Найдите assert в заголовках библиотеки (при условии, что это реальные файлы в вашей файловой системе) и замените его недопустимым элементом

// #define assert(condition) ... /* old definition */
#define assert(condition) ((condition) & "PLEASE DO NOT USE ASSERT" = 42)
0
ответ дан 6 December 2019 в 06:50
поделиться

Если исходный код находится под вашим контролем:

#define NDEBUG
// Before
#include <assert.h>
// Or other header that includes assert.h

Или используйте предварительно скомпилированный заголовок или параметры компиляции для определения NDEBUG .

Для двоичных файлов третьих сторон используйте выпуск их версия.

1
ответ дан 6 December 2019 в 06:50
поделиться

assert () обычно #define ' d должен быть ((void) 0) для кода выпуска ( #define NDEBUG ), поэтому нет накладных расходов вообще .

При использовании тестовая версия, не влияют ли накладные расходы на производительность, чтобы тестирование было реалистичным?

1
ответ дан 6 December 2019 в 06:50
поделиться