Studiowałem samouczki OpenCV i natknąłem się na tę assert
funkcję; co to robi?
Studiowałem samouczki OpenCV i natknąłem się na tę assert
funkcję; co to robi?
Odpowiedzi:
assert
zakończy program (zwykle z komunikatem cytującym instrukcję assert), jeśli jego argument okaże się fałszywy. Jest to powszechnie używane podczas debugowania, aby program w bardziej oczywisty sposób zawiódł, jeśli wystąpi nieoczekiwany warunek.
Na przykład:
assert(length >= 0); // die if length is negative.
Możesz także dodać bardziej pouczający komunikat, który będzie wyświetlany, jeśli tak się nie powiedzie:
assert(length >= 0 && "Whoops, length can't possibly be negative! (didn't we just check 10 lines ago?) Tell jsmith");
Lub inaczej:
assert(("Length can't possibly be negative! Tell jsmith", length >= 0));
Podczas wykonywania kompilacji wydania (bez debugowania) można również usunąć narzut związany z ocenianiem assert
instrukcji, definiując NDEBUG
makro, zwykle za pomocą przełącznika kompilatora. Następstwem tego jest to, że twój program nigdy nie powinien polegać na działającym makrze assert.
// BAD
assert(x++);
// GOOD
assert(x);
x++;
// Watch out! Depends on the function:
assert(foo());
// Here's a safer way:
int ret = foo();
assert(ret);
Z kombinacji programu wywołującego abort () i bez zagwarantowania, że zrobi cokolwiek, twierdzenia powinny być używane tylko do testowania rzeczy, które programista założył, a nie na przykład przez wprowadzenie liczby zamiast litery (która powinna być obsługiwane w inny sposób).
assert
zwykle zgłasza wyjątek” - w C ++ nie powstaje „wyjątek”, który nazywa przerwaniem… jest trochę inny.
#
znak nie wprowadza komentarza.
assert("error message", expression)
Assert oświadczenie komputer jest analogiczna do rachunku Upewnij się w języku angielskim.
Spojrzeć na
przykładowy program assert () w C ++
Wiele kompilatorów oferuje makro assert (). Makro assert () zwraca wartość PRAWDA, jeśli jego parametr ocenia wartość PRAWDA i podejmuje działanie, jeśli ocenia wartość FAŁSZ. Wiele kompilatorów przerwie program z powodu niepowodzenia assert (); inni zgłoszą wyjątek
Jedną z potężnych funkcji makra assert () jest to, że preprocesor nie zwija go w żaden kod, jeśli DEBUG nie jest zdefiniowany. Jest to wielka pomoc podczas programowania, a kiedy produkt końcowy jest wysyłany, nie ma ograniczenia wydajności ani wzrostu wielkości wykonywalnej wersji programu.
Na przykład
#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
Funkcja assert () może diagnozować błędy programu. W C jest on zdefiniowany w <assert.h>
, aw C ++ jest zdefiniowany w <cassert>
. Jego prototyp to
void assert(int expression);
Wyrażeniem argumentu może być wszystko, co chcesz przetestować - zmienna lub dowolne wyrażenie C. Jeśli wyrażenie ma wartość PRAWDA, assert () nic nie robi. Jeśli wyrażenie ma wartość FAŁSZ, assert () wyświetla komunikat o błędzie na stderr i przerywa wykonywanie programu.
Jak używasz assert ()? Najczęściej służy do śledzenia błędów programu (które różnią się od błędów kompilacji). Błąd nie uniemożliwia kompilacji programu, ale powoduje, że daje on niepoprawne wyniki lub działa nieprawidłowo (na przykład blokuje się). Na przykład program analizy finansowej, który piszesz, może czasami dawać nieprawidłowe odpowiedzi. Podejrzewasz, że problem jest spowodowany zmienną interest_rate przyjmującą wartość ujemną, co nigdy nie powinno się zdarzyć. Aby to sprawdzić, umieść instrukcję
assert (stopa_oprocentowania> = 0); w miejscach w programie, w których używana jest stopa_odsetek. Jeśli zmienna kiedykolwiek stanie się ujemna, makro assert () wyświetli ostrzeżenie. Następnie możesz sprawdzić odpowiedni kod, aby zlokalizować przyczynę problemu.
Aby zobaczyć, jak działa assert (), uruchom poniższy przykładowy program . Jeśli wprowadzisz wartość niezerową, program wyświetli tę wartość i zakończy się normalnie. Jeśli wpiszesz zero, makro assert () wymusza nieprawidłowe zakończenie programu. Dokładny komunikat o błędzie zależy od kompilatora, ale oto typowy przykład:
Asercja nie powiodła się: x, plik list19_3.c, wiersz 13 Zauważ, że aby assert () działał, twój program musi być skompilowany w trybie debugowania. Informacje na temat włączania trybu debugowania znajdują się w dokumentacji kompilatora (jak wyjaśniono za chwilę). Podczas późniejszej kompilacji ostatecznej wersji w trybie wydania makra assert () są wyłączone.
int x;
printf("\nEnter an integer value: ");
scanf("%d", &x);
assert(x >= 0);
printf("You entered %d.\n", x);
return(0);
Wprowadź wartość całkowitą: 10
Wpisałeś 10.
Wprowadź wartość całkowitą: -1
Komunikat o błędzie: Nieprawidłowe zakończenie programu
Twój komunikat o błędzie może się różnić w zależności od systemu i kompilatora, ale ogólny pomysł jest taki sam.
Rzeczy takie jak „podnosi wyjątek” i „zatrzymuje wykonywanie” mogą być prawdziwe dla większości kompilatorów, ale nie dla wszystkich. (BTW, czy istnieją twierdzenia, które naprawdę zgłaszają wyjątki?)
Oto interesujące, nieco inne znaczenie asercji używane przez c6x i inne kompilatory TI: po obejrzeniu niektórych instrukcji aser, te kompilatory wykorzystują informacje zawarte w tej instrukcji do przeprowadzenia pewnych optymalizacji. Niegodziwy.
Przykład w C:
int dot_product(short *x, short *y, short z)
{
int sum = 0
int i;
assert( ( (int)(x) & 0x3 ) == 0 );
assert( ( (int)(y) & 0x3 ) == 0 );
for( i = 0 ; i < z ; ++i )
sum += x[ i ] * y[ i ];
return sum;
}
To mówi de kompilatorowi, że tablice są wyrównane do granic 32-bitowych, więc kompilator może generować określone instrukcje wykonane dla tego rodzaju wyrównania.
Wersja standardowa C ++ 11 N3337
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
19.3 Twierdzenia
1 Nagłówek <csert>, opisany w (Tabela 42), zawiera makro do dokumentowania asercji programu C ++ oraz mechanizm wyłączania kontroli asercji.
2 Zawartość jest taka sama jak nagłówek biblioteki Standard C <assert.h>.
Wersja standardowa C99 N1256
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
7.2 Diagnostyka <assert.h>
1 Nagłówek
<assert.h>
definiuje makro assert i odnosi się do innego makra,NDEBUG
które nie jest zdefiniowane przez<assert.h>
. JeśliNDEBUG
jest zdefiniowane jako nazwa makra w punkcie pliku źródłowego, w którym znajduje się <assert.h>, makro assert jest definiowane po prostu jako#define assert(ignore) ((void)0)
Makro assert jest redefiniowane zgodnie z bieżącym stanem NDEBUG za każdym razem, gdy
<assert.h>
jest dołączane.2. Makro potwierdzające jest realizowane jako makro, a nie jako rzeczywista funkcja. Jeśli definicja makra zostanie pominięta w celu uzyskania dostępu do faktycznej funkcji, zachowanie jest niezdefiniowane.
7.2.1 Diagnostyka programu
7.2.1.1 Makro asertywne
Streszczenie
1.
#include <assert.h> void assert(scalar expression);
Opis
2 Makro assert umieszcza testy diagnostyczne w programach; rozwija się w pustkę. Gdy jest wykonywane, jeśli wyrażenie (które powinno mieć typ skalarny) jest fałszywe (to znaczy porównuje równe 0), makro potwierdzenia zapisuje informacje o konkretnym wywołaniu, które się nie powiodło (w tym tekst argumentu, nazwa plik źródłowy, numer linii źródłowej i nazwa funkcji zamykającej - te ostatnie to odpowiednio wartości makr przetwarzania wstępnego
__FILE__
i__LINE__
identyfikatora__func__
) w standardowym strumieniu błędów w formacie zdefiniowanym przez implementację. 165) Następnie wywołuje funkcję przerwania.Zwroty
3 Makro aser nie zwraca żadnej wartości.
Istnieją trzy główne powody używania funkcji assert () w porównaniu do normalnej metody if if i printf
Funkcja assert () jest używana głównie w fazie debugowania, żmudne jest pisanie za pomocą instrukcji printf za każdym razem, gdy chcesz przetestować warunek, który może nawet nie dostać się do końcowego kodu.
W dużych wdrożeniach oprogramowania funkcja assert jest bardzo przydatna, gdy kompilator może ignorować instrukcje assert przy użyciu zdefiniowanego makra NDEBUG przed połączeniem pliku nagłówka z funkcją assert ().
assert () przydaje się, gdy projektujesz funkcję lub jakiś kod i chcesz dowiedzieć się, jakie ograniczenia będzie działał, a kod nie zadziała, a na końcu dołącz, jeśli jeszcze, do oceny go w zasadzie grając z założeniami.
Jest to funkcja, która zatrzyma wykonywanie programu, jeśli oceniona przez nią wartość jest fałszywa. Zazwyczaj jest on otoczony przez makro, dzięki czemu nie jest kompilowany w wynikowy plik binarny po skompilowaniu z ustawieniami wersji.
Jest przeznaczony do testowania przyjętych założeń. Na przykład:
void strcpy(char* dest, char* src){
//pointers shouldn't be null
assert(dest!=null);
assert(src!=null);
//copy string
while(*dest++ = *src++);
}
Idealnym rozwiązaniem jest to, że możesz popełnić błąd w swoim programie, na przykład wywołać funkcję z niepoprawnymi argumentami, a trafisz na aser, zanim ulegnie on awarii (lub nie działa zgodnie z oczekiwaniami)
Ponadto można go użyć do sprawdzenia, czy alokacja dynamiczna zakończyła się powodzeniem.
Przykład kodu:
int ** p;
p = new int * [5]; // Dynamic array (size 5) of pointers to int
for (int i = 0; i < 5; ++i) {
p[i] = new int[3]; // Each i(ptr) is now pointing to a dynamic
// array (size 3) of actual int values
}
assert (p); // Check the dynamic allocation.
Podobny do:
if (p == NULL) {
cout << "dynamic allocation failed" << endl;
exit(1);
}
new
Zgłasza wyjątek w przypadku niepowodzenia alokacji, chyba że podasz nothrow
(czego nie tutaj). Co więcej, twoje formatowanie jest dziwne i exit
złe.
assert()
służy tylko do debugowania i oznaczania rzeczy, które nigdy, nigdy, nigdy nie powinny się wydarzyć - na długo przed wydaniem kompilacji wydania.