Как я могу справиться с целочисленным переполнением?

Попробуйте это, надеюсь, это вам поможет.

<EditText
        android:id="@+id/xValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:hint="xValue" />
2
задан NAZMUL HUSSAIN 19 January 2019 в 14:32
поделиться

3 ответа

strtol преобразует значение в long int, диапазон которого может отличаться от int. Кроме того, он возвращает LONG_MAX или LONG_MIN, если значение может быть преобразовано, но находится за пределами диапазона для long int. В этом случае для errno будет установлено значение ERANGE (но не иначе!) Кроме того, в случае сбоя сопоставления возвращаемое значение равно 0, но errno не установлено; но ep указывает на начало строки.

int isInt (char *s)
{
   char *ep = NULL;

   // zero errno first!
   errno = 0;
   long i = strtol (s, &ep, 10);
   if (errno) {
       return 0;
   }

   // matching failure.
   if (ep == s) {
       return 0;
   }

   // garbage follows
   if (! ((*ep == 0) || (!strcmp(ep,"\n")))) {
      return 0;
   }

   // it is outside the range of `int`
   if (i < INT_MIN || i > INT_MAX) {
      return 0;
   }

   return 1; 
} 

То, что dbush говорит об использовании perror, верно. strtol устанавливает ошибку только в случае переполнения long, что не является единственно возможным случаем сбоя в вашей функции, поэтому perror может напечатать что-нибудь вроде Is a directory или Multihop attempted.

0
ответ дан Antti Haapala 19 January 2019 в 14:32
поделиться

sscanf(buffer, any_format_without_width, &anytype); недостаточно , недостаточно для обнаружения переполнения.

, если результат преобразования не может быть представлен в объекте, поведение не определено. C11dr §7.21.6.2 10

Не используйте семейство *scanf() для обнаружения переполнения. Это может работать в некоторых случаях, но не в целом.


Вместо этого используйте функции strto**(). Тем не менее, даже ОП isInt() неправильно закодированы, поскольку неправильно оценивают isInt("\n"), isInt(""), isInt("999..various large values ...999") как хорошие int с.

Альтернатива:

bool isint_alt(const char *s) {
  char *endptr;
  errno = 0;
  long y = strtol(s, &endptr, 10);

  if (s == endptr) {
    return false; // No conversion
  }

  if (errno == ERANGE) {
    return false; // Outside long range
  }

  if (y < INT_MIN || y > INT_MAX) {
    return false; // Outside int range
  }

  // Ignore trailing white space
  while (isspace((unsigned char)*endptr)) {
    endptr++;
  }

  if (*endptr) {
    return false; // Trailing junk
  }

  return true;
}
0
ответ дан chux 19 January 2019 в 14:32
поделиться

Если кто-то должен использовать sscanf() для обнаружения переполнения int, а не надежного strtol(), существует громоздкий способ.

Используйте более широкий тип и ограничение ширины, чтобы предотвратить переполнение при сканировании.

bool isint_via_sscanf(const char *s) {
  long long y;
  int n = 0;
  if (sscanf(s, "18%lld %n", &y, &n) != 1) {  // Overflow not possible
    return false;  // Conversion failed 
  }

  if (y < INT_MIN || y > INT_MAX) {
    return false; // Outside int range
  }

  if (s[n]) {
    return false;  // Trailing junk
  }

  return true;  
}

Недостаточно на редких платформах, где INT_MAX > 1e18.

Также неверно возвращает ввод, такой как "lots of leading space and/or lot of leading zeros 000123", как недействительный.

Более сложный код, использующий sscanf(), может устранить эти недостатки, но лучший подход - strto*().

0
ответ дан chux 19 January 2019 в 14:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: