Diğerlerinin de işaret ettiği gibi, assert
programcı hatalarına karşı asla gerçekleşmemesi gereken son savunma tablonuzdur. Bunlar, gemi gönderene kadar sağa ve sola başarısız olmamasını sağlayan sağlık kontrolleridir.
Ayrıca , geliştiricilerin yararlı bulabilecekleri her ne nedenle olursa olsun: estetik, performans, istedikleri her şey istikrarlı sürüm yapılarından çıkarılacak şekilde tasarlanmıştır . Bir hata ayıklama derlemesini bir sürüm derlemesinden ayıran şeyin bir parçasıdır ve tanım gereği bir sürüm derlemesi bu tür iddialardan yoksundur. Dolayısıyla , bir önişlemci tanımı olan ve tanımlanmamış bir sürüm oluşturmaya yönelik bir girişim olacak olan analog "yerinde onaylarla sürüm yayınını" serbest bırakmak istiyorsanız tasarımın bir alt _DEBUG
dalması vardır NDEBUG
; artık gerçek bir sürüm değil.
Tasarım, standart kütüphaneye bile uzanır. Sayısız arasında çok temel bir örnek olarak, uygulamalarında bir çok std::vector::operator[]
olacak assert
bir aklı kontrol Eğer sınırların dışında vektör kontrol etmiyor emin olmak. Ve bir sürüm derlemesinde bu tür kontrolleri etkinleştirirseniz standart kütüphane çok, çok daha kötü performans göstermeye başlayacaktır. Karşılaştırmasıvector
kullanılarakoperator[]
ve eski düz bir dinamik diziye karşı dahil edilen bu tür iddialara sahip bir doldurma ctoru, siz bu tür kontrolleri devre dışı bırakana kadar dinamik dizinin genellikle çok daha hızlı olduğunu gösterir, bu nedenle performansı çok önemsiz yollardan çok uzakta yaparlar. Burada boş bir işaretçi denetimi ve sınır dışı bir denetim, bu tür denetimler, akıllı bir işaretçiyi silmek veya bir diziye erişmek kadar basit olan koddan önceki kritik döngülerdeki her kareye milyonlarca kez uygulanıyorsa, büyük bir masraf haline gelebilir.
Bu nedenle, büyük olasılıkla iş için farklı bir araç ve kilit alanlarda bu tür sağlık kontrolleri yapan sürüm derlemelerinden çıkarılmak üzere tasarlanmamış bir araç istiyorsunuz. Kişisel olarak bulduğum en faydalı günlük kaydı. Bu durumda, kullanıcı bir hata rapor ettiğinde, bir günlük eklerse işler çok daha kolay hale gelir ve günlüğün son satırı, hatanın nerede oluştuğu ve ne olabileceği konusunda bana büyük bir ipucu verir. Daha sonra, hata ayıklama derlemesinde adımlarını yeniden oluşturduktan sonra, bir onaylama hatası alabilirim ve bu onaylama hatası bana zamanımı düzene koymak için büyük ipuçları veriyor. Günlüğe kaydetme nispeten pahalı olduğundan, genel bir veri yapısında bir dizinin sınırlardan erişilemediğinden emin olmak gibi son derece düşük düzeyli sağlık kontrolleri uygulamak için kullanmıyorum.
Yine de son olarak ve sizinle biraz anlaşarak, alfa testi sırasında test cihazlarına bir hata ayıklama derlemesine benzeyen bir şey vermek isteyebileceğiniz makul bir durum görebilirim, örneğin, bir NDA imzalayan küçük bir alfa test grubuyla . Test cihazlarınızı, çalıştırdıkları testler ve yazılımı çalıştırırken daha ayrıntılı çıktı gibi bazı hata ayıklama / geliştirme özellikleriyle birlikte bazı hata ayıklama bilgileriyle birlikte tam sürüm derlemesinden başka bir şey verirseniz, alfa testini düzene sokabilir. En azından alfa için böyle şeyler yapan büyük oyun şirketleri gördüm. Ancak bu, test kullanıcılarına gerçekten bir sürüm derlemesi dışında bir şey vermeye çalıştığınız alfa veya dahili test gibi bir şey içindir. Aslında bir sürüm derlemesi göndermeye çalışıyorsanız, tanım gereği,_DEBUG
"debug" ve "release" derlemeleri arasındaki farkı gerçekten karıştıran başka bir şey.
Bu kod yayınlanmadan önce neden kaldırılmalıdır? Kontroller çok bir performans kaybı değildir ve başarısız olursa kesinlikle daha doğrudan bir hata mesajı tercih ediyorum bir sorun var.
Yukarıda belirtildiği gibi, kontroller performans açısından önemsiz olmak zorunda değildir. Birçoğu muhtemelen önemsizdir, ancak yine de standart lib bunları kullanıyor ve std::vector
optimize edilmiş bir sürüm derlemesi olarak 4 kat daha uzun sürdüğü takdirde, birçok durumda performansı kabul edilemez bir şekilde etkileyebilir. çünkü asla başarısız olması gerekmeyen kontrolleri.
Eski bir ekipte, aslında hata ayıklama yapılarının daha hızlı çalışmasını sağlamak için matris ve vektör kütüphanemizin bazı kritik yolları bazı eklemeleri hariç tutması gerekiyordu, çünkü bu varsayımlar matematik işlemlerini olduğu noktaya kadar büyük ölçüde yavaşlatıyordu. ilgi kodunu bile izleyebilmemiz için 15 dakika beklememizi gerektiriyordu. Meslektaşlarım aslındaasserts
çünkü bunu yapmanın büyük bir fark yarattığını fark ettiler. Bunun yerine, kritik hata ayıklama yollarından kaçınmaya karar verdik. Bu kritik yolları sınır kontrolünden geçmeden doğrudan vektör / matris verilerini kullandığımızda, tam işlemi gerçekleştirmek için gereken süre (sadece vektör / matris matematiğinden fazlasını içeren) dakikalardan saniyelere indirildi. Bu aşırı bir durum ama kesinlikle varsayımlar performans açısından her zaman ihmal edilemez, hatta yakın bile değil.
Ama aynı zamanda bu şekilde asserts
tasarlandı. Tahtada bu kadar büyük bir performans etkisi olmadıysa, bir hata ayıklama oluşturma özelliğinden daha fazlası olarak tasarlandıysa ya da vector::at
sürüm oluşturmalarında bile sınırların kontrol edilmesini ve sınırların dışına çıkmasını içeren bunları kullanabiliriz erişim (ör. büyük bir performans isabeti ile). Ancak şu anda, durumlarımdaki büyük performans etkileri göz önüne alındığında, tasarımları çok daha yararlı buluyorum NDEBUG
, tanımlandığında sadece atlanan bir hata ayıklama-oluştur özelliği . En azından birlikte çalıştığım vakalar için, ilk etapta asla başarısız olmaması gereken akıl sağlığı kontrollerini dışlamak, bir sürüm derlemesi için büyük bir fark yaratıyor.
vector::at
vs. vector::operator[]
Bu iki yöntemin ayrımı, bunun yanı sıra alternatifin de merkezinde yer alıyor: istisnalar. vector::operator[]
tipik assert
olarak sınırların dışında erişimin bir sınırın dışında bir vektöre erişmeye çalışırken kolayca tekrarlanabilir bir hatayı tetikleyeceğinden emin olmak için kullanılır. Ancak kütüphane uygulayıcıları bunu, optimize edilmiş bir sürüm derlemesinde bir kuruşa mal olmayacağı varsayımıyla yapıyorlar.
Bu arada vector::at
her zaman sınırları kontrol durumlar o yapar ve serbest bırakma oluşturur bile atar temin ama sık sık çok daha kod kullanarak bkz noktasına buna bir performans kaybına sahiptir vector::operator[]
daha vector::at
. C ++ tasarımının birçoğu "kullandığınız / ihtiyaç duyduğunuz şey için ödeme yapın" fikrini yansıtır ve birçok insan genellikle, tercih operator[]
ettikleri fikrine dayanarak, sürüm yapılarını kontrol eden sınırlarla bile uğraşmaz. Optimize edilmiş sürüm yapılarında sınırların kontrol edilmesi gerekmez. Aniden sürüm derlemelerinde iddialar etkinleştirilirse, bu ikisinin performansı aynı olur ve vektör kullanımı her zaman dinamik bir diziden daha yavaş olur. Dolayısıyla, iddiaların tasarımının ve faydasının büyük bir kısmı, bir sürüm derlemesinde özgür olmaları fikrine dayanmaktadır.
release_assert
Bu niyetleri keşfettikten sonra bu ilginç. Doğal olarak herkesin kullanım durumları farklı olurdu, ama ben release_assert
kontrol yapmak ve yayın sürümlerinde bile bir satır numarası ve hata mesajı gösteren yazılım çökecek bazı kullanım bulabilirsiniz düşünüyorum .
Benim durumumda, bir istisna atıldığında olduğu gibi yazılımın zarif bir şekilde iyileşmesini istemediğim bazı belirsiz durumlar için olurdu. Yazılımın hiç gerçekleşmemesi gereken bir şeyle karşılaştığında kullanıcıya rapor vermek için bir satır numarası verilebilmesi için bu durumlarda bile çökmesini istiyorum, yine de harici giriş hataları değil, programcı hataları için akıl kontrolü istisnalar, ancak serbest bırakılma maliyeti hakkında endişelenmeden yapılacak kadar ucuz.
Aslında ben bir sürümde tutmak için yeterince ucuz olabilir atılan bir istisna zarifçe kurtarmak için tercih edilen bir satır numarası ve hata mesajı ile sabit bir çökme bulabilirsiniz bazı durumlar vardır . Ve mevcut bir durumdan kurtarmaya çalışırken karşılaşılan bir hata gibi, bir istisnadan kurtarmanın imkansız olduğu bazı durumlar vardır. Orada release_assert(!"This should never, ever happen! The software failed to fail!");
kontrol için ilk etapta olağanüstü bir yol içinde yapılacak ve normal yürütme yollarında hiçbir maliyeti olmayacak çünkü bir ve doğal olarak kir ucuz olurdu mükemmel bir uyum bulur .