2008-10-15 5 views
6

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

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

Как тип данных для текущей позиции и размера чтения, я использовал 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 не было лучшей идеей в первую очередь.

Любые идеи?

EDIT: Я ищу решение для языка C!

+0

какая версия gcc вы используете? Похоже, что они сделали size_t без знака в версиях после и включительно 2.4 – 2008-10-15 21:04:52

+0

Версии, с которыми мне приходится иметь дело, повсюду. Я занимаюсь программированием, и иногда мне приходится использовать версии компилятора из каменного века. – 2008-10-15 21:08:02

+0

«Подписанность» - обычное слово. – Lassi 2016-10-28 09:00:08

ответ

11

Что касается подписания ли 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 как беззнаковый типа, и подлинник «fixincludes» будет массировать системы sys/types.h, чтобы не конфликта с этим.

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

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

4

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

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

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

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

+0

GCC определяет size_t как подписанный :( – 2008-10-15 21:02:18

+0

Не unsigned long 32 бит в 64-битных окнах? Не хорошее предположение для size_t. – ejgottl 2008-10-15 21:05:04

0

Использование 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: link text

0

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

temp = value_to_be_added_to; 

value_to_be_added_to += value_to_add; 

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

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

2

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

4

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

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

Смежные вопросы