SORU
15 EKİM 2010, Cuma


Tespit C/C taşması imzaladı

İlk bakışta, bu soru gerçekten önemli ölçüde farklıdır ancak http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c, kopyası gibi görünebilir.

İşaretsiz bir tamsayı taşması tespit ederken oldukça önemsiz olduğunu, bir tespit buldumimzaladıC/C taşması aslında çoğu insanın düşündüğünden daha zordur.

Bunu en bariz, henüz naif, böyle bir şey olabilir:

int add(int lhs, int rhs)
{
 int sum = lhs   rhs;
 if ((lhs >= 0 && sum < rhs) || (lhs < 0 && sum > rhs)) {
  /* an overflow has occurred */
  abort();
 }
 return sum; 
}

Bu sorunu C standardına göre, imzalı bir tamsayı taşmasıtanımsız davranış.Bu standarda göre, diğer bir deyişle, hatta imzalı taşmasına neden bitmez, programınızı null bir işaretçi başvuru yapıldı eğer kadar geçersiz. Tanımsız davranışlara neden olamaz, ve aslında sonra taşması tespit etmeye çalışın o zaman, yukarıdaki gibi post-durumu örnek kontrol edin.

Yukarıdaki kontrol birçok Derleyiciler üzerinde çalışma ihtimali olsa bile, buna emin olabilirsin. C standart işaretli tamsayı taşması tanımsız olduğunu söylüyor, çünkü aslında, bazı Derleyiciler (GCC gibi) derleyici imzalı bir taşma imkansız olduğunu varsayar çünkü optimizasyon bayrak ayarlandığında 16**. Bu tamamen taşma kontrol etmek için girişimde keser.

Yani, taşma kontrol etmek için başka bir şekilde mümkün olabilir:

int add(int lhs, int rhs)
{
 if (lhs >= 0 && rhs >= 0) {
  if (INT_MAX - lhs <= rhs) {
   /* overflow has occurred */
   abort();
  }
 }
 else if (lhs < 0 && rhs < 0) {
  if (lhs <= INT_MIN - rhs) {
   /* overflow has occurred */
   abort();
  }
 }

 return lhs   rhs;
}

Bu aslında bir eklenti böyle bir sahne taşmasına neden olmayacak önceden sağlıyoruz kadar iki tamsayı birbirine ekleyin bilemiyoruz daha umut verici görünüyor. Böylece, tanımsız davranışlara neden bilmiyoruz.

Ancak, bu çözüm sadece ayrıca operasyonun işe yarayıp yaramayacağını test etmek için çıkarma işlemi gerçekleştirmek zorunda beri ne yazık ki bir çok ilk çözüm daha az etkilidir. Ve eğer (küçük) bu performans isabet umrunda bile, yine de tamamen bu çözüm yeterli olup olmadığından emin değilim. İfadesi lhs <= INT_MIN - rhs tam olarak derleyici hemen iyileştir diye ifade gibi, imzalı taşması imkansız olduğunu düşünüyor gibi görünüyor.

Bu yüzden orada daha iyi bir çözüm burada mı? 1 garantili bir şeyi) tanımsız davranışlara neden, ve 2) taşma denetimleri optimize uzakta için bir fırsat ile derleyici bulunur? Düşünüyordum da olabilir, bir şekilde artık döküm her iki işlenen imzasız, ve sahne kontrolleri ile çalışırken kendi iki tamamlayıcı aritmetik, ama pek emin değilim Bunu nasıl yapacağımı.

CEVAP
16 EKİM 2010, CUMARTESİ


Eğer ayarlarsanız . hayır, 2. kodunuzu doğru değil, ama yaklaştın:

int half = INT_MAX/2;
int half1 = half   1;

ayrıca bir sonucu INT_MAX. (INT_MAX her zaman tek sayıdır). Bu geçerli bir giriş. Ama rutin 10* *olacak ve görev iptal olur. Yanlış pozitif.

Bu hata hem denetler <= yerine < koyarak tamir edilebilir.

Ama o zaman da kod uygun değil. Aşağıdakileri yapın:

int add(int lhs, int rhs)
{
 if (lhs >= 0) {
  if (INT_MAX - lhs < rhs) {
   /* overflow has occurred */
   abort();
  }
 }
 else {
  if (rhs < INT_MIN - lhs) {
   /* overflow has occurred */
   abort();
  }
 }
 return lhs   rhs;
}

Bu geçerli olduğunu görmek için, sembolik olarak eşitsizliklerin her iki tarafta lhs eklemek zorunda, ve bu neden yasak olduğunu tam olarak aritmetik koşullar verir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Joshua Benedict

    Joshua Bened

    26 EKİM 2013
  • SuicideSheeep

    SuicideSheee

    8 Ocak 2012
  • TouchePro

    TouchePro

    27 EYLÜL 2007