“Assert” işlevi nedir?


262

Ben OpenCV öğreticiler okudum ve assertfonksiyonu rastlamak ; bu ne işe yarıyor?


20
Man assert notuna dikkat edin: "assert () bir makro olarak uygulanır; test edilen ifadenin yan etkileri varsa, program davranışı NDEBUG'un tanımlanıp tanımlanmadığına bağlı olarak farklı olacaktır. ."
Johannes Schaub - litb


35
@ S.Lott şimdi Google'da arama yapan kişiler, bu sayfayı en iyi arama sonuçlarından biri olarak bulacak ve sorularına iyi bir hakemli derleme yanıtı sunacak ve aynı zamanda Yığın Taşmasını destekleyecek, bu yüzden benden +1!
Matt Grum

6
Benden -1. En iyi arama sonucu OP'nin en başta danışması gereken belgeler olmalıdır .
Yörüngedeki Hafiflik Yarışları

9
@LightnessRacesinOrbit. Bana tembel deyin, ancak sizin gibi bilgili SO kullanıcılarının sağladığı mükemmel yoğunlaştırılmış, özetlenmiş ve açıklanmış dokümantasyon okumalarını kullanmayı tercih ederim. İçten teşekkürlerimi :)
Tyson Hilmer

Yanıtlar:


298

assertbağımsız değişkeninin yanlış olduğu ortaya çıkarsa programı (genellikle onaylama ifadesini gösteren bir mesajla) sonlandıracaktır. Hata ayıklama sırasında, beklenmedik bir durum ortaya çıkarsa programın daha açık bir şekilde başarısız olmasını sağlamak için yaygın olarak kullanılır.

Örneğin:

assert(length >= 0);  // die if length is negative.

Bu şekilde başarısız olursa, görüntülenmesi için daha bilgilendirici bir mesaj da ekleyebilirsiniz:

assert(length >= 0 && "Whoops, length can't possibly be negative! (didn't we just check 10 lines ago?) Tell jsmith");

Ya da bunun gibi:

assert(("Length can't possibly be negative! Tell jsmith", length >= 0));

Bir sürüm (hata ayıklama olmayan) derlemesi yaparken , genellikle derleyici anahtarıyla makro asserttanımlayarak deyimlerin değerlendirilme yükünü de kaldırabilirsiniz NDEBUG. Bunun sonucu, programınızın asla çalışan makroya güvenmemesidir.

// 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);

Abort () yöntemini çağıran ve hiçbir şey yapmayı garanti etmeyen programın birleşiminden, geliştiricilerin örneğin örneğin bir harf yerine bir sayı ( başka yollarla ele alınabilir).


49
" assertgenellikle bir istisna yükseltir" - C ++ 'da "istisna" diyor iptal diyor ... biraz farklı.
Artyom

5
Bu cevabın soru etiketli dillerle (C ve C ++) ilgili olduğunu düşünmüyorum. C ve C ++ 'da, assert bir istisna oluşturmaz, argümanı etrafında parantezler vardır ve #karakter bir yorum sunmaz.
Steve Jessop

Seçenekleriniz şunlardır: Cevabı topluluk-wiki yapın ve eski şeyleri kaldırarak sorunuzu düzenleyin ve diğerlerinden doğru bilgileri yerleştirmelerini isteyin. Bu şekilde, aşağı oylar temsilcinizi etkilemez ve insanlar yanıtı geliştirebilir.
Johannes Schaub - litb

2
uzunluk NaN ise uzunluk> = 0 da yanlış olur
Andreas

1
Şu anda, VS 2015'te, hata mesajı içeren iddia, çalışmadığı için çalışmaz. O olmalıassert("error message", expression)
Dooskington

102

Assert bilgisayar deyim deyimi benzerdir emin marka İngilizce.


131
Pek iyi değil. “Işığın kapalı olduğundan emin olun”, “ışığın kapalı olup olmadığını kontrol edin” anlamına gelmez, “ışığın kapalı olup olmadığına bakın ve eğer patlamazsa lütfen patlayın” anlamına gelmez. “Çift kontrol ”'ün daha yakın bir çeviri olduğunu söyleyebilirim.
Luke Maurer

7
@Luke, İngiliz dilinin harikalarını gösteren, dilin aynı şeyi söylemenin birçok yolu sunduğundan. Ancak iddiayı düşünün (uzunluk> 0). Böylece "uzunluğun sıfırdan büyük olduğunu iki kez kontrol etmek" veya "uzunluğun sıfırdan büyük olduğundan emin olmak" için çevirebiliriz . Her iki seçenek de açıkça çalışırken, yine de benimkini tercih ediyorum;)
Blake7

4
Ama diğer yorum “ uzunluğu sıfırdan büyük yapmak ” tır. Yani biraz daha belirsizlik var.
Luke Maurer

29
İngilizce "iddia" fiili ile daha yakından benzer
Steve Carter

Gerçekten de, "emin olun" ifadesi "kontrol edin ve uygun değilse değiştirin" olarak yorumlanabilir.
Erik Bongers

14

Şuna baksana

C ++ 'da assert () örnek programı

Birçok derleyici bir assert () makrosu sunar. Assert () makrosu, parametresi TRUE değerini değerlendirirse TRUE değerini döndürür ve FALSE değerini değerlendirirse bir tür işlem yapar. Birçok derleyici başarısız bir assert () üzerinde programı iptal edecektir; diğerleri bir istisna atacak

Assert () makrosunun güçlü özelliklerinden biri, DEBUG tanımlanmamışsa önişlemcinin kodu hiç kod içine daraltmamasıdır. Geliştirme sırasında büyük bir yardımcıdır ve nihai ürün gönderildiğinde, programın yürütülebilir sürümünün boyutunda herhangi bir performans cezası veya artış yoktur.

Örneğin

#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

11
"NDEBUG tanımlanmışsa" olmamalıdır?
RichN

2
Bu "çok derleyici" ne hakkında? MSVC ve GCC'nin her ikisi de bu standartla uyumludur. Hangi uyumlu olmayan derleyiciler: iddia yok; bir onay yazdığında bir mesaj yazdırmayın ve iptal etmeyin; uygun NDEBUG yerine DEBUG kullanın?
Steve Jessop

lmao, elbette bu çok yanlış anlıyor java-samples adlı bir web sitesi .
underscore_d

6

Assert () işlevi program hatalarını tanılayabilir. C de tanımlanır <assert.h>ve C ++ da tanımlanır <cassert>. Prototipi

void assert(int expression);

Bağımsız değişken ifadesi test etmek istediğiniz herhangi bir şey olabilir - bir değişken veya herhangi bir C ifadesi. İfade TRUE olarak değerlendirilirse assert () hiçbir şey yapmaz. İfade YANLIŞ olarak değerlendirilirse, assert () stderr'de bir hata mesajı görüntüler ve programın yürütülmesini durdurur.

Assert () nasıl kullanılır? En sık program hatalarını izlemek için kullanılır (bunlar derleme hatalarından farklıdır). Bir hata, bir programın derlenmesini engellemez, ancak yanlış sonuçlar vermesine veya düzgün çalışmamasına neden olur (örneğin kilitleme). Örneğin, yazdığınız bir finansal analiz programı bazen yanlış cevaplar verebilir. Sorunun, faiz_oranı değişkeninin negatif bir değer almasından kaynaklandığından şüpheleniyorsunuz. Bunu kontrol etmek için ifadeyi yerleştirin

onaylama (faiz_oranı = = 0); faiz_oranının kullanıldığı programdaki konumlarda. Değişken negatif olursa, assert () makrosu sizi uyarır. Daha sonra sorunun nedenini bulmak için ilgili kodu inceleyebilirsiniz.

Assert () işlevinin nasıl çalıştığını görmek için aşağıdaki örnek programı çalıştırın . Sıfır olmayan bir değer girerseniz, program değeri görüntüler ve normal olarak sona erer. Sıfır girerseniz, assert () makrosu anormal program sonlandırmasını zorlar. Gördüğünüz tam hata mesajı derleyicinize bağlı olacaktır, ancak tipik bir örnek:

Onaylama başarısız oldu: x, dosya list19_3.c, satır 13 assert () işlevinin çalışması için programınızın hata ayıklama modunda derlenmesi gerektiğini unutmayın. Hata ayıklama modunu etkinleştirme hakkında bilgi için derleyici belgelerinize bakın (bir anda açıklandığı gibi). Daha sonra son sürümü yayın modunda derlediğinizde, assert () makroları devre dışı bırakılır.

 int x;

 printf("\nEnter an integer value: ");
 scanf("%d", &x);

 assert(x >= 0);

 printf("You entered %d.\n", x);
 return(0);

Bir tamsayı değeri girin: 10

10 girdiniz.

Bir tamsayı değeri girin: -1

Hata Mesajı: Anormal program sonlandırma

Hata mesajınız sisteminize ve derleyicinize bağlı olarak değişebilir, ancak genel fikir aynıdır.


Örnek programınızın iddia ile nasıl çalıştığını açıkladınız. İddianın kendisi nasıl çalıştığı değil. Programı anormal olarak nasıl bitirir? bir tür istisna atıyor mu? Ne tür? Özel bir sinyal oluşturuyor mu? ne sinyali? İddialar herhangi bir C ++ deneme yakalama mekanizması tarafından "yakalanabilir" mi?
Motti Shneor

4

'İstisna yükseltir' ve 'yürütmeyi durdurur' gibi şeyler çoğu derleyici için geçerli olabilir, ancak herkes için geçerli olmayabilir. (BTW, gerçekten istisnalar getiren iddia beyanları var mı?)

İşte c6x ve diğer TI derleyicileri tarafından kullanılan ilginç, biraz farklı bir assert anlamı: belirli iddia ifadelerini gördükten sonra, bu derleyiciler belirli optimizasyonları gerçekleştirmek için bu ifadedeki bilgileri kullanır. Wicked.

C ile Örnek:

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;
}

Bu derleyiciye dizilerin 32 bitlik sınırlarda hizalandığını söyler, böylece derleyici bu tür bir hizalama için özel talimatlar üretebilir.


1
Peki, iddia yanlışsa ve NDEBUG ayarlanmamışsa ne yaparlar? Bu <assert.h> öğesinden onaylama sürümü ise, standart bir ileti yazdırıp iptal etmesini gerektirir. Açıkçası standart, ifadenin gerçeğine dayanarak optimize edilmelerine izin verilmediğini söylemez, ancak uyumlu olmak için, yanlışsa hala iptal etmeleri gerekir.
Steve Jessop

1
onlar standart davranış takip
stijn

1

C ++ 11 N3337 standart taslak

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

19.3 İddialar

1 (Tablo 42) 'de açıklanan <cassert> başlığı, C ++ program iddialarını belgelemek için bir makro ve onaylama kontrollerini devre dışı bırakmak için bir mekanizma sağlar.

2 İçerik, Standart C kitaplık başlığı <assert.h> ile aynıdır.

C99 N1256 standart taslak

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

7.2 Teşhis <assert.h>

1 Üstbilgi <assert.h>, onaylama makrosunu tanımlar ve NDEBUGtarafından tanımlanmayan başka bir makrosu belirtir <assert.h>. Eğer NDEBUG<assert.h> dahildir kaynak dosyada noktada makro adı olarak tanımlanmaktadır, assert makrosu basitçe olarak tanımlanır

 #define assert(ignore) ((void)0)

Assert makrosu, her <assert.h>dahil edildiğinde geçerli NDEBUG durumuna göre yeniden tanımlanır .

2. İddia makrosu, gerçek bir fonksiyon olarak değil, bir makro olarak uygulanacaktır. Gerçek bir işleve erişmek için makro tanımı bastırılırsa, davranış tanımsızdır.

7.2.1 Program teşhisi

7.2.1.1 Onay makrosu

özet

1.

#include <assert.h>
void assert(scalar expression);

Açıklama

2 İddia makrosu teşhis testlerini programlara koyar; geçersiz bir ifadeye genişler. Yürütüldüğünde, ifade (skaler tipte olacaktır) yanlışsa (yani 0'a eşitse), onaylama makrosu başarısız olan belirli çağrı hakkında (bağımsız değişkenin metni, kaynak dosya, kaynak satır numarası ve ekteki fonksiyonun adı - ikincisi sırasıyla ön tanımlı makroların __FILE__ve __LINE__ve tanımlayıcının değerleridir __func__) uygulama tarafından tanımlanan bir formatta standart hata akışındaki değerleridir. 165) Daha sonra iptal işlevini çağırır.

İadeler

3 Onaylama makrosu hiçbir değer döndürmez.


1

Assert () işlevinin normalse normalde ve printf üzerinde kullanılmasının üç ana nedeni vardır.

  1. assert () işlevi çoğunlukla hata ayıklama aşamasında kullanılır, son kodda bile yol almayacak bir koşulu her test etmek istediğinizde başka bir printf deyimi ile yazmak sıkıcıdır.

  2. Büyük yazılım dağıtımlarında assert, derleyicinin assert () işlevi için başlık dosyasını bağlamadan önce tanımlanan NDEBUG makrosunu kullanarak assert deyimlerini yoksaymasını sağlayabileceğiniz çok kullanışlı bir yöntemdir.

  3. assert (), bir işlev veya bazı kod tasarlarken ve kodun hangi sınırlarla çalışıp çalışmayacağı konusunda bir fikir edinmek istediğinizde kullanışlı olur ve son olarak temelde varsayımlarla oynamak için bir başka if içerir.


0

Değerlendirdiği değer yanlışsa programın yürütülmesini durduracak bir işlevdir. Genellikle bir makro ile çevrelenir, böylece serbest bırakma ayarlarıyla derlendiğinde sonuçtaki ikili dosyaya derlenmez.

Yaptığınız varsayımları test etmek için tasarlanmıştır. Örneğin:

void strcpy(char* dest, char* src){
    //pointers shouldn't be null
    assert(dest!=null);
    assert(src!=null);

    //copy string
    while(*dest++ = *src++);
}

İstediğiniz ideal, programınızda geçersiz bağımsız değişkenlere sahip bir işlevi çağırmak gibi bir hata yapabilmeniz ve segfaults (veya beklendiği gibi çalışmazsa) önce bir onaylayıcıya basmanızdır.


neden sadece if & else kullanmıyoruz ve bazı günlük bilgileri ekliyoruz?
Asad Khan

1
Çünkü strcpy için boş gösterici geçirmemelisiniz. Olmaması gereken şeylerden biri. Bir boş gösterici geçildiyse, daha üst düzeydeki bir şeyin bozulduğunu gösterir. En iyi ihtimalle beklenmedik veri değerleri nedeniyle (programın yanlış veya null olması) programı sorundan daha fazla çökertmeniz gerekir.
Yacoby

-5

Ayrıca, dinamik ayırmanın başarılı olup olmadığını kontrol etmek için kullanabilirsiniz.

Kod örneği:

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.

Benzer:

if (p == NULL) {
    cout << "dynamic allocation failed" << endl;
    exit(1);
}

3
Hayır newbelirttiğiniz sürece tahsisat hatası üzerinde bir istisna atar nothrow(burada yoktu). Dahası, biçimlendirmeniz garip ve exitşeytani.
Yörüngedeki Hafiflik Yarışları

Evet haklısın. Ben eklemeyi unuttum. Çıkış yerine nasıl kullanacağınızı görmek isterdim
Sadikov

1
@Sadikov Herkes , yayın modunda oluştururken tamamen kaldırılmayan kodu kullanarak böyle bir hata koşulunu işleyecek , böylece kullanıcılarınızı koruma olmadan ve bir ön koşul karşılanmadığında tanımlanmamış davranışların merhametine bırakacak ve bu sayede hiç kontrol ve yakalanmadı . assert()yalnızca bir sürüm derlemesi yapılmadan çok önce , asla , asla gerçekleşmeyecek şeylerin hatalarını ayıklamak ve damgalamak içindir .
underscore_d
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.