Потенциальная проблема со стандартными malloc'ing символами C - PullRequest
7 голосов
/ 08 октября 2009

Отвечая на комментарий к другому моему ответу здесь , я обнаружил, что может быть дырой в стандарте C (c1x, я не проверял ранее и да, я знаю, что невероятно маловероятно, что я один среди всех жителей планеты нашел ошибку в стандарте). Информация следует:

  1. Раздел 6.5.3.4 («Оператор sizeof») в параграфе 2 гласит: "The sizeof operator yields the size (in bytes) of its operand".
  2. Параграф 3 этого раздела гласит: "When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1".
  3. Раздел 7.20.3.3 описывает void *malloc(size_t sz), но все, что он говорит, это "The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate". В нем вообще не упоминается, какие единицы используются для аргумента.
  4. Приложение E запускает 8 - это минимальное значение для CHAR_BIT, поэтому длина символов может быть более одного байта.

Мой вопрос просто такой:

В среде, где символ имеет ширину 16 бит, выделит ли malloc(10 * sizeof(char)) 10 символов (20 байтов) или 10 байтов? Точка 1 выше указывает на первое, точка 2 указывает на второе.

Кто-нибудь с большим C-standard-fu, чем я, может ответить на этот вопрос?

Ответы [ 3 ]

16 голосов
/ 08 октября 2009

В 16-битной char среде malloc(10 * sizeof(char)) выделит 10 char с (10 байт), потому что если char равно 16 битам, то эта архитектура / реализация определяет байт как 16 бит. char это не октет, это байт. На старых компьютерах это может быть больше, чем 8-битный де-факто стандарт, который мы имеем сегодня.

Соответствующий раздел из стандарта C следует:

3.6 Термины, определения и символы

байт - адресуемая единица хранения данных, достаточно большая, чтобы вместить любого члена базового набора символов среды выполнения ...

ПРИМЕЧАНИЕ 2. - Байт состоит из непрерывной последовательности битов, число которых определяется реализацией.

2 голосов
/ 08 октября 2009

В стандарте C99 строгая корреляция между байтами char и размером объекта приведена в 6.2.6.1/4 "Представления типов - Общие сведения":

Значения, хранящиеся в объектах без битовых полей любого другого типа объекта, состоят из n × CHAR_BIT битов, где n - это размер объекта этого типа в байтах. Значение может быть скопировано в объект типа unsigned char [n] (например, memcpy); результирующий набор байтов называется объектным представлением значения.

В стандарте C ++ такое же соотношение дано в 3.9 / 2 «Типы»:

Для любого объекта (кроме подобъекта базового класса) типа POD T, независимо от того, содержит ли объект допустимое значение типа T, базовые байты (1.7), составляющие объект, могут быть скопированы в массив char или unsigned char. Если содержимое массива char или unsigned char копируется обратно в объект, объект должен впоследствии сохранять свое первоначальное значение.

В C90, как представляется, явно не упоминается корреляция, но между определением байта, определением символа и определением оператора sizeof можно сделать вывод, что char тип эквивалентен байту.

Также обратите внимание, что количество бит в байте (и количество бит в char) определяется реализацией - строго говоря, оно не должно быть 8 бит. И в другом месте в комментарии говорится, что DSP обычно имеют байты с числом битов, не равным 8.

Обратите внимание, что RFC и стандарты IETF обычно (всегда?) Используют термин «октет» вместо «байт», чтобы однозначно сказать, что единицы, о которых они говорят, имеют ровно 8 бит - не больше, не меньше.

1 голос
/ 08 октября 2009

Разве единицы измерения "size_t sz" не входят в адресуемую единицу вашей архитектуры? Я работаю с DSP, адреса которого соответствуют 32-битным значениям, а не байтов. malloc (1) возвращает мне указатель на 4-байтовую область.

...