Обратите внимание на примечание от man assert: «assert () реализован как макрос; если у протестированного выражения есть побочные эффекты, поведение программы будет отличаться в зависимости от того, определен ли NDEBUG. Это может создать гейзенговские ошибки, которые исчезают, когда включена отладка «.
@ S.Lott теперь люди, которые ищут в Google, найдут эту страницу одним из лучших результатов поиска, предоставляя хороший рецензированный ответ на свой вопрос и одновременно продвигая переполнение стека, так что это +1 от меня!
Мэтт Грум
6
Это -1 от меня. Лучшим результатом поиска должна быть документация , к которой ОП должен был обратиться в первую очередь.
Гонки легкости на орбите
9
@LightnessRacesinOrbit. Называйте меня ленивым, но я предпочитаю использовать превосходные сжатые, обобщенные и объясненные чтения документации, которую предоставляют такие опытные пользователи SO, как вы. Мое сердечное спасибо :)
Тайсон Хилмер
Ответы:
298
assertзавершит программу (обычно с сообщением, цитирующим оператор assert), если его аргумент окажется ложным. Он обычно используется во время отладки, чтобы сделать программу более очевидной, если возникает непредвиденное состояние.
Например:
assert(length >=0);// die if length is negative.
Вы также можете добавить более информативное сообщение, которое будет отображаться в случае сбоя, например:
assert(length >=0&&"Whoops, length can't possibly be negative! (didn't we just check 10 lines ago?) Tell jsmith");
Или еще так:
assert(("Length can't possibly be negative! Tell jsmith", length >=0));
Когда вы делаете релизную (не отладочную) сборку, вы также можете устранить накладные расходы при оценке assertоператоров, определив NDEBUGмакрос, обычно с помощью переключателя компилятора. Следствием этого является то, что ваша программа никогда не должна полагаться на запущенный макрос assert.
// BADassert(x++);// GOODassert(x);
x++;// Watch out! Depends on the function:assert(foo());// Here's a safer way:int ret = foo();assert(ret);
Исходя из комбинации программы, вызывающей abort () и не гарантирующей что-либо делать, утверждения следует использовать только для проверки того, что разработчик предположил, а не, например, для ввода пользователем числа, а не буквы (что должно быть обрабатывается другими средствами).
« assertобычно вызывает исключение» - в C ++ оно не вызывает «исключение», которое вызывает abort ... оно немного отличается.
Артём
5
Я не думаю, что этот ответ относится к тем же языкам, на которых задан вопрос (C и C ++). В C и C ++ assert не вызывает исключение, оно имеет круглые скобки вокруг своего аргумента, а #символ не вводит комментарий.
Стив Джессоп
Вот ваши варианты: Сделайте ответ на вики-сообществе и отредактируйте свой вопрос, удалив старый материал, попросив других разместить правильную информацию. Таким образом, отрицательные отзывы не повлияют на вашу репутацию, и люди могут улучшить ответ.
Йоханнес Шауб -
2
длина> = 0 также станет ложной, если длина равна NaN
Andreas
1
В настоящее время в VS 2015 утверждение с сообщением об ошибке не будет работать, поскольку оно вышло из строя. Это должно бытьassert("error message", expression)
Dooskington
102
Утверждают , компьютер утверждение аналогично высказыванию убедитесь , что на английском языке.
Ну, не совсем. «Убедитесь, что свет выключен» означает «проверьте свет и выключите его, если он включен», а не «посмотрите, выключен ли свет и, если нет, пожалуйста, взорвитесь». Я бы сказал, что «двойная проверка» - это более близкий перевод.
Люк Маурер
7
@Luke, который иллюстрирует чудеса английского языка, потому что язык предлагает много способов сказать то же самое. Но рассмотрим утверждение (длина> 0). Таким образом, мы можем перевести это как «перепроверить длину больше нуля» или «убедиться, что длина больше нуля» . Хотя оба варианта работают четко, я все же предпочитаю свой;)
Blake7
4
Хорошо, но другая интерпретация такова: « сделайте длину больше нуля». Так что тут немного больше двусмысленности.
Люк Маурер
29
Это более близко аналогично английскому глаголу «утверждать»
Стив Картер
В самом деле, «убедитесь» можно интерпретировать как «проверить, а если нет, изменить».
Многие компиляторы предлагают макрос assert (). Макрос assert () возвращает TRUE, если его параметр оценивает TRUE, и предпринимает какие-то действия, если он оценивает FALSE. Многие компиляторы прерывают программу при сбое assert (); другие бросят исключение
Одна из мощных особенностей макроса assert () состоит в том, что препроцессор вообще не сворачивает его в код, если DEBUG не определен. Это отличная помощь во время разработки, и когда конечный продукт поставляется, нет снижения производительности и увеличения размера исполняемой версии программы.
Например
#include<stdio.h>#include<assert.h>void analyze (char*,int);int main(void){char*string="ABC";int length =3;
analyze(string, length);
printf("The string %s is not null or empty, ""and has length %d \n",string, length);}void analyze(char*string,int length){assert(string!= NULL);/* cannot be NULL */assert(*string!='\0');/* cannot be empty */assert(length >0);/* must be positive */}/**************** Output should be similar to ******************
The string ABC is not null or empty, and has length 3
О чем говорят многие компиляторы? MSVC и GCC оба соответствуют стандартам на этом. Какие несовместимые компиляторы: не имеют assert; не печатать сообщение и не прерывать работу при сбое подтверждения; использовать DEBUG вместо правильного NDEBUG?
Стив Джессоп
Имао, конечно, это веб-сайт под названием java-samples, который так ошибается.
underscore_d
6
Функция assert () может диагностировать программные ошибки. В C он определен в <assert.h>, а в C ++ - в <cassert>. Его прототип
voidassert(int expression);
Выражением аргумента может быть все, что вы хотите проверить - переменная или любое выражение C. Если выражение имеет значение TRUE, assert () ничего не делает. Если выражение имеет значение FALSE, assert () отображает сообщение об ошибке в stderr и прерывает выполнение программы.
Как вы используете assert ()? Чаще всего он используется для отслеживания программных ошибок (которые отличаются от ошибок компиляции). Ошибка не препятствует компиляции программы, но приводит к тому, что она дает неверные результаты или работает неправильно (например, блокировка). Например, программа финансового анализа, которую вы пишете, может иногда давать неправильные ответы. Вы подозреваете, что проблема вызвана тем, что переменная Interest_rate принимает отрицательное значение, которое никогда не должно происходить. Чтобы проверить это, поместите заявление
assert (Interest_rate> = 0); в местах в программе, где используется Interest_rate. Если переменная становится отрицательной, макрос assert () предупреждает вас. Затем вы можете изучить соответствующий код, чтобы найти причину проблемы.
Чтобы увидеть, как работает assert (), запустите пример программы ниже . Если вы введете ненулевое значение, программа отобразит это значение и завершится нормально. Если вы введете ноль, макрос assert () вызывает аварийное завершение программы. Точное сообщение об ошибке будет зависеть от вашего компилятора, но вот типичный пример:
Ошибка подтверждения: x, файл list19_3.c, строка 13 Обратите внимание, что для работы assert () ваша программа должна быть скомпилирована в режиме отладки. Обратитесь к документации вашего компилятора для получения информации о включении режима отладки (как объяснено ниже). При последующей компиляции окончательной версии в режиме выпуска макросы assert () отключаются.
int x;
printf("\nEnter an integer value: ");
scanf("%d",&x);assert(x >=0);
printf("You entered %d.\n", x);return(0);
Введите целое значение: 10
Вы ввели 10.
Введите целое значение: -1
Сообщение об ошибке: аварийное завершение программы
Ваше сообщение об ошибке может отличаться в зависимости от вашей системы и компилятора, но общая идея та же.
Вы объяснили, как ваша программа-пример работает с assert. Не так, как самоутверждение работает. Как это ненормально завершает программу? это бросает какое-то исключение? Какой? Это создает специальный сигнал? какой сигнал? Могут ли утверждения быть "перехвачены" каким-либо механизмом C ++ try-catch?
Мотти Шнеор
4
Такие вещи, как «вызывает исключение» и «прекращение выполнения» могут быть верными для большинства компиляторов, но не для всех. (Кстати, существуют ли утверждения assert, которые действительно генерируют исключения?)
Вот интересное, немного другое значение assert, используемое c6x и другими компиляторами TI: увидев определенные операторы assert, эти компиляторы используют информацию в этом операторе для выполнения определенных оптимизаций. Злой.
Пример в C:
int dot_product(short*x,short*y,short z){int sum =0int i;assert(((int)(x)&0x3)==0);assert(((int)(y)&0x3)==0);for( i =0; i < z ;++i )
sum += x[ i ]* y[ i ];return sum;}
Это говорит де-компилятору, что массивы выровнены по 32-битным границам, поэтому компилятор может генерировать конкретные инструкции, сделанные для такого типа выравнивания.
Так что же они делают, если assert ложен, а NDEBUG не установлен? Если это версия assert из <assert.h>, то стандарт требует, чтобы он распечатал сообщение и прервал его. Очевидно, что в стандарте не говорится, что им не разрешено оптимизировать, основываясь на правдивости утверждения, но чтобы соответствовать требованиям, им все равно придется прервать работу, если она ложная.
1 Заголовок <cassert>, описанный в (Таблица 42), предоставляет макрос для документирования утверждений программы C ++ и механизм для отключения проверок утверждений.
2 Содержимое совпадает с заголовком стандартной библиотеки C <assert.h>.
1 Заголовок <assert.h>определяет макрос assert и ссылается на другой макрос, NDEBUGкоторый не определен <assert.h>. Если NDEBUGопределяется как имя макроса в той точке исходного файла, в которую включен <assert.h>, макрос assert определяется просто как
#defineassert(ignore)((void)0)
Макрос assert переопределяется в соответствии с текущим состоянием NDEBUG при каждом
<assert.h>включении.
2. Макрос утверждения должен быть реализован как макрос, а не как фактическая функция. Если определение макроса подавлено для доступа к реальной функции, поведение не определено.
7.2.1 Программа диагностики
7.2.1.1 Макрос утверждения
конспект
1.
#include<assert.h>voidassert(scalar expression);
Описание
2 Макрос assert помещает диагностические тесты в программы; оно расширяется до пустого выражения. Когда оно выполняется, если выражение (которое должно иметь скалярный тип) имеет значение false (то есть сравнивает значение, равное 0), макрос assert записывает информацию о конкретном вызове, который не удался (включая текст аргумента, имя исходный файл, номер исходной строки и имя включающей функции - последние являются соответственно значениями макросов предварительной обработки __FILE__и __LINE__и идентификатора
__func__) в стандартном потоке ошибок в формате, определяемом реализацией. 165) Затем вызывается функция прерывания.
Существует три основных причины использования функции assert () по сравнению с обычными if else и printf
Функция assert () в основном используется на этапе отладки, и утомительно писать, если еще с оператором printf, каждый раз, когда вы хотите проверить условие, которое может даже не попасть в окончательный код.
В больших развертываниях программного обеспечения assert очень удобен, когда вы можете заставить компилятор игнорировать операторы assert, используя макрос NDEBUG, определенный перед связыванием файла заголовка для функции assert ().
assert () пригодится, когда вы разрабатываете функцию или некоторый код и хотите получить представление о том, какие ограничения будет и не будет работать с кодом, и, наконец, включить if else для его оценки, в основном играя с предположениями.
Это функция, которая останавливает выполнение программы, если оцененное значение равно false. Обычно он окружен макросом, так что он не компилируется в результирующий двоичный файл при компиляции с настройками выпуска.
Он предназначен для проверки сделанных вами предположений. Например:
void strcpy(char* dest,char* src){//pointers shouldn't be nullassert(dest!=null);assert(src!=null);//copy stringwhile(*dest++=*src++);}
В идеале вы хотите, чтобы вы могли сделать ошибку в вашей программе, например, вызвать функцию с недопустимыми аргументами, и вы нажали assert до того, как он вышел из строя (или не работает должным образом)
почему мы просто не используем if & else и не добавляем информацию для регистрации?
Асад Хан
1
Потому что вы никогда не должны передавать пустой указатель на strcpy. Это одна из тех вещей, которые не должны происходить. Если нулевой указатель был передан, это означает, что что-то на более высоком уровне испортилось. В лучшем случае вам в конечном итоге приходится отказывать программе дальше от проблемы из-за неожиданных значений данных (либо dest неверно, либо null).
Якоби
-5
Кроме того, вы можете использовать его для проверки успешности динамического размещения.
Пример кода:
int** p;
p =newint*[5];// Dynamic array (size 5) of pointers to intfor(int i =0; i <5;++i){
p[i]=newint[3];// Each i(ptr) is now pointing to a dynamic// array (size 3) of actual int values}assert(p);// Check the dynamic allocation.
Нет. newВыдает исключение при ошибке выделения, если вы не укажете nothrow(чего вы здесь не сделали). Кроме того, ваше форматирование странное и exitзлое.
Гонки легкости на орбите
Да ты прав. Я забыл добавить не. Очень хотелось бы посмотреть, как ты будешь использовать вместо выхода
Садыков
1
@Sadikov Любой другой мог бы обработать такое состояние ошибки, используя код, который не был полностью удален при сборке в режиме выпуска , таким образом оставляя ваших пользователей без защиты и во власти неопределенного поведения, если предварительное условие не выполнено и, благодаря этому, выполняется ни разу не проверял и не ловил . assert()предназначен только для отладки и удаления вещей, которые никогда не должны происходить никогда - задолго до того, как будет выпущена сборка релиза.
Ответы:
assert
завершит программу (обычно с сообщением, цитирующим оператор assert), если его аргумент окажется ложным. Он обычно используется во время отладки, чтобы сделать программу более очевидной, если возникает непредвиденное состояние.Например:
Вы также можете добавить более информативное сообщение, которое будет отображаться в случае сбоя, например:
Или еще так:
Когда вы делаете релизную (не отладочную) сборку, вы также можете устранить накладные расходы при оценке
assert
операторов, определивNDEBUG
макрос, обычно с помощью переключателя компилятора. Следствием этого является то, что ваша программа никогда не должна полагаться на запущенный макрос assert.Исходя из комбинации программы, вызывающей abort () и не гарантирующей что-либо делать, утверждения следует использовать только для проверки того, что разработчик предположил, а не, например, для ввода пользователем числа, а не буквы (что должно быть обрабатывается другими средствами).
источник
assert
обычно вызывает исключение» - в C ++ оно не вызывает «исключение», которое вызывает abort ... оно немного отличается.#
символ не вводит комментарий.assert("error message", expression)
Утверждают , компьютер утверждение аналогично высказыванию убедитесь , что на английском языке.
источник
Взгляни на
Пример программы assert () на C ++
Например
источник
Функция assert () может диагностировать программные ошибки. В C он определен в
<assert.h>
, а в C ++ - в<cassert>
. Его прототипВыражением аргумента может быть все, что вы хотите проверить - переменная или любое выражение C. Если выражение имеет значение TRUE, assert () ничего не делает. Если выражение имеет значение FALSE, assert () отображает сообщение об ошибке в stderr и прерывает выполнение программы.
Как вы используете assert ()? Чаще всего он используется для отслеживания программных ошибок (которые отличаются от ошибок компиляции). Ошибка не препятствует компиляции программы, но приводит к тому, что она дает неверные результаты или работает неправильно (например, блокировка). Например, программа финансового анализа, которую вы пишете, может иногда давать неправильные ответы. Вы подозреваете, что проблема вызвана тем, что переменная Interest_rate принимает отрицательное значение, которое никогда не должно происходить. Чтобы проверить это, поместите заявление
assert (Interest_rate> = 0); в местах в программе, где используется Interest_rate. Если переменная становится отрицательной, макрос assert () предупреждает вас. Затем вы можете изучить соответствующий код, чтобы найти причину проблемы.
Чтобы увидеть, как работает assert (), запустите пример программы ниже . Если вы введете ненулевое значение, программа отобразит это значение и завершится нормально. Если вы введете ноль, макрос assert () вызывает аварийное завершение программы. Точное сообщение об ошибке будет зависеть от вашего компилятора, но вот типичный пример:
Ошибка подтверждения: x, файл list19_3.c, строка 13 Обратите внимание, что для работы assert () ваша программа должна быть скомпилирована в режиме отладки. Обратитесь к документации вашего компилятора для получения информации о включении режима отладки (как объяснено ниже). При последующей компиляции окончательной версии в режиме выпуска макросы assert () отключаются.
Введите целое значение: 10
Вы ввели 10.
Введите целое значение: -1
Сообщение об ошибке: аварийное завершение программы
Ваше сообщение об ошибке может отличаться в зависимости от вашей системы и компилятора, но общая идея та же.
источник
Такие вещи, как «вызывает исключение» и «прекращение выполнения» могут быть верными для большинства компиляторов, но не для всех. (Кстати, существуют ли утверждения assert, которые действительно генерируют исключения?)
Вот интересное, немного другое значение assert, используемое c6x и другими компиляторами TI: увидев определенные операторы assert, эти компиляторы используют информацию в этом операторе для выполнения определенных оптимизаций. Злой.
Пример в C:
Это говорит де-компилятору, что массивы выровнены по 32-битным границам, поэтому компилятор может генерировать конкретные инструкции, сделанные для такого типа выравнивания.
источник
C ++ 11 N3337 стандартная версия
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
19.3 Утверждения
C99 N1256 стандартная тяга
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
7.2 Диагностика <assert.h>
7.2.1 Программа диагностики
7.2.1.1 Макрос утверждения
источник
Существует три основных причины использования функции assert () по сравнению с обычными if else и printf
Функция assert () в основном используется на этапе отладки, и утомительно писать, если еще с оператором printf, каждый раз, когда вы хотите проверить условие, которое может даже не попасть в окончательный код.
В больших развертываниях программного обеспечения assert очень удобен, когда вы можете заставить компилятор игнорировать операторы assert, используя макрос NDEBUG, определенный перед связыванием файла заголовка для функции assert ().
assert () пригодится, когда вы разрабатываете функцию или некоторый код и хотите получить представление о том, какие ограничения будет и не будет работать с кодом, и, наконец, включить if else для его оценки, в основном играя с предположениями.
источник
Это функция, которая останавливает выполнение программы, если оцененное значение равно false. Обычно он окружен макросом, так что он не компилируется в результирующий двоичный файл при компиляции с настройками выпуска.
Он предназначен для проверки сделанных вами предположений. Например:
В идеале вы хотите, чтобы вы могли сделать ошибку в вашей программе, например, вызвать функцию с недопустимыми аргументами, и вы нажали assert до того, как он вышел из строя (или не работает должным образом)
источник
Кроме того, вы можете использовать его для проверки успешности динамического размещения.
Пример кода:
Похожий на:
источник
new
Выдает исключение при ошибке выделения, если вы не укажетеnothrow
(чего вы здесь не сделали). Кроме того, ваше форматирование странное иexit
злое.assert()
предназначен только для отладки и удаления вещей, которые никогда не должны происходить никогда - задолго до того, как будет выпущена сборка релиза.