переполнения в дополнениях size_t - PullRequest
8 голосов
/ 16 октября 2008

Мне нравится, когда мой код предупрежден для VS.NET и GCC, и я хочу, чтобы мой код был готов к 64-битной версии.

Сегодня я написал небольшой модуль, который работает с буферами памяти и обеспечивает доступ к данным через интерфейс в стиле файла (например, вы можете читать байты, записывать байты, искать и т. Д.).

В качестве типа данных для текущей позиции и размера чтения я использовал size_t, поскольку это наиболее естественный выбор. Я получаю предупреждения, и они должны работать и в 64-битной среде.

На всякий случай: моя структура выглядит так:

typedef struct
{
  unsigned char * m_Data;
  size_t          m_CurrentReadPosition;
  size_t          m_DataSize;
} MyMemoryFile;

Подпись size_t, по-видимому, не определена на практике. Поиск кода Google подтвердил это.

Теперь передо мной стоит дилемма: я хочу проверить дополнения с помощью size_t на переполнение, потому что мне приходится иметь дело с предоставленными пользователем данными, а сторонние библиотеки будут использовать мой код. Тем не менее, для проверки переполнения я должен знать значение. Это имеет огромное значение в реализации.

Итак, какого черта я должен писать такой код независимо от платформы и компилятора?

Можно ли проверить подпись size_t во время выполнения или во время компиляции? Это решило бы мою проблему. Или, может быть, size_t была не самой лучшей идеей.

Есть идеи?

РЕДАКТИРОВАТЬ : Я ищу решение для языка C!

Ответы [ 6 ]

12 голосов
/ 16 октября 2008

Относительно того, является ли size _t подписанным или неподписанным и GCC (из старого руководства GCC - я не уверен, что он все еще там):

Существует потенциальная проблема с size_t тип и версии GCC до выпустить 2.4. ANSI C требует, чтобы size_t всегда будет неподписанным типом. За совместимость с существующими системами заголовочные файлы, GCC определяет size_t в stddef.h быть любым типом sys/types.h системы определяет его быть. Большинство систем Unix, которые определяют size_t в sys/types.h, определите его как быть подписанным типом. Некоторый код в библиотека зависит от size_t беззнаковый тип, и не будет работать правильно, если оно подписано.

Код библиотеки GNU C, который ожидает size_t быть неподписанным - это правильно. определение size_t как подписанного типа это неверно. Мы планируем это в версии 2.4, GCC всегда будет определять size_t как тип без знака, а Сценарий «fixinclude» будет массажировать sys/types.h системы, чтобы не конфликт с этим.

А пока мы работаем над этим проблема, говоря GCC явно используйте тип без знака для size_t, когда компиляция библиотеки GNU C. 'configure' автоматически обнаружит какой тип GCC использует для size_t переопределить его при необходимости.

Если вы хотите подписанную версию size_t, используйте ptrdiff_t или в некоторых системах есть typedef для ssize_t.

4 голосов
/ 16 октября 2008

size_t - это целочисленный тип без знака в соответствии со стандартами C ++ C. Любая реализация, имеющая подпись size_t, серьезно не соответствует требованиям и, вероятно, также имеет другие проблемы с переносимостью. Гарантируется, что при переполнении вы можете обернуться, что означает, что вы можете написать тесты типа if (a + b < a) для обнаружения переполнения.

size_t - отличный тип для всего, что связано с памятью. Вы делаете это правильно.

4 голосов
/ 16 октября 2008

size_t должен быть без знака.

Обычно он определяется как unsigned long.

Я никогда не видел, чтобы это было определено иначе. ssize_t является его подписанным аналогом.

EDIT: GCC определяет его как подписанный в некоторых обстоятельствах. компиляция в режиме ASNI C или std-99 должна привести к тому, что он будет без знака.

2 голосов
/ 16 октября 2008

Для языка C используйте IntSafe . Также выпущено Microsoft (не путать с библиотекой C ++ SafeInt). IntSafe - это набор вызовов функций языка Си, которые могут выполнять математические операции и безопасно выполнять преобразования. обновленный URL для функций intsafe

0 голосов
/ 16 октября 2008

Я не уверен, правильно ли я понимаю вопрос, но, может быть, вы можете сделать что-то вроде:

temp = value_to_be_added_to;

value_to_be_added_to += value_to_add;

if (temp > value_to_be_added_to)
{
  overflow...
}

Так как он вернется к более низким значениям, вы можете легко проверить, не переполнен ли он.

0 голосов
/ 16 октября 2008

Используйте safeint . Это класс, разработанный Майклом Ховардом и выпущенный как открытый исходный код от Microsoft. Он предназначен для работы с целыми числами, где переполнение идентифицируется как риск. Все переполнения преобразуются в исключения и обрабатываются. Класс предназначен для облегчения правильного использования.

Например:

char CouldBlowUp(char a, char b, char c)
{
   SafeInt<char> sa(a), sb(b), sc(c);

   try
   {
     return (sa * sb + sc).Value();
   }
   catch(SafeIntException err)
   {
      ComplainLoudly(err.m_code);
   }

   return 0;
}

Кроме того, safeint часто используется в Microsoft в таких продуктах, как Office.

Ref: текст ссылки

...