обработка выделенной памяти как другого типа - PullRequest
0 голосов
/ 30 ноября 2010

Предположим, я выделил немного памяти.

char* buffer = (char*)my_malloc(2062);

Я присваиваю значения char первым 14 байтам из ранее определенного массива с именем header.

memcpy(buffer, header, 14);

Тогда я хочу обработать оставшуюся часть выделенного пространства как указатели для плавания.

float* float_buffer = (float*)(buffer + 14);
some_function(float_buffer);

Затем, в какой-то момент позже мне нужно отправить все данные.

transmit(buffer);
my_free(buffer);

Это правильный способ лечения памяти? Поплавок * приведен нормально? У меня возникают проблемы, когда я теряю ценности и не получаю правильных результатов. Мой вопрос: Если вам приходится обрабатывать выделенную память как разные типы, но затем отправлять ее как char * в конце обработки ..... это правильный способ сделать это?

Я проверил значения ptr, и они одинаковые, когда они являются float * и char *, но я не получаю правильный результат.

Одно из моих ограничений заключается в том, что я могу изначально выделить только один блок памяти из статического буфера. Поэтому нельзя вызывать другой malloc другого типа (float *).

Ответы [ 3 ]

3 голосов
/ 30 ноября 2010

Концептуально это нормально - но вам нужно проделать дополнительную работу, чтобы обеспечить его надежную работу.

Потенциальная проблема заключается в том, что вы не можете просто получить доступ к любому произвольному адресу как float. Могут быть определенные требования выравнивание - адрес, возвращаемый malloc(), должен быть правильно выровнен для доступа любого типа, но как только вы добавите 14 к этому адресу, все ставки отключены (кроме char).

Чтобы обеспечить правильное выравнивание, вы должны убедиться, что адрес, который вы добавляете к buffer, кратен sizeof(float). Вы можете сделать это, добавив отступ, используя следующую формулу:

#define PAD_OFFSET(offset, type) ((offset) + sizeof(type) - 1) & ~(sizeof(type) - 1))

float *float_buffer = (float *)(buffer + PAD_OFFSET(14, float));

Обратите внимание, что это создаст разрыв - отступ - между вашими символами и вашими поплавками.

В качестве альтернативы, вы можете определить struct, и компилятор определит для вас отступы. При этом используется функция C99, называемая гибкий элемент массива :

struct foo {
    char abc[14];
    float xyz[];
};

struct foo *buffer = malloc(2062);
memcpy(&buffer->abc, header, 14);
some_function(&buffer->xyz);
transmit(buffer); /* Presuming transmit() expects a void * parameter. */

Если вы хотите сделать это без заполнения , вы не можете напрямую обращаться к памяти в buffer как плавающие значения - вам нужно будет создать временный массив и скопировать его в:

float temp[500]; /* Or whatever size */
some_function(&temp);
memcpy(buffer + 14, temp, sizeof temp);
3 голосов
/ 30 ноября 2010

Чтобы это работало (по крайней мере, переносимо), вы должны были бы убедиться (как минимум), что float_buffer был выровнен по размеру (float).Это можно сделать, выделив sizeof (float) - 1 дополнительный байт, наблюдая за результатом вызова malloc по модулю sizeof (float) и игнорируя первые несколько байтов в зависимости от ситуации.(Вы, конечно, должны были бы сохранить исходный указатель, чтобы сделать вызов free ().)

Вы, вероятно, не хотите этого делать.Похоже, что цель «буфера» состоит в том, чтобы накапливать данные для отправки по сети или что-то в этом роде, и что плавающие объекты будут скопированы откуда-то еще.Что вам действительно нужно сделать, так это привести в обратном направлении: всегда обращаться с буфером как с символом [], а при копировании их заново интерпретировать исходные значения как последовательность символов.То есть

char* buffer = malloc(total_size);
char* float_start = buffer + header_size;
memcpy(float_start, (char*)float_source, sizeof(float) * float_count);
transmit(buffer, total_size);
free(buffer);
0 голосов
/ 30 ноября 2010

Я размышляю здесь, но поскольку прототипом для malloc является

void *malloc(size_t size);

, вы по существу приводите буфер типа void * к char *, поэтому последующее приведение другого фрагмента буфера к float * будетвсе будет хорошо, если вы позаботитесь о правильном учете указателей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...