2013-05-31 2 views
1

Я хотел бы выделить память для буфера, который будет содержать через memcpy в будущем структуру, содержащую указатель, который ранее был динамически распределенной памятью.Получение размера структуры, содержащей динамически выделенную память

То есть, у меня есть на структуру

struct test_struct { 
    int num; 
    char *values; 
}; 

Где test_struct.values содержит num количество строк длины LENGTH. Я знаю, что я не могу получить размер памяти, указатель был выделен, поэтому я просто отслеживаю его через num. Каков самый простой/чистый способ получить размер этой структуры?

Единственное решение, которое я могу придумать что-то вроде

buf = malloc(sizeof(test_struct) + (num * LENGTH));

Но я новичок в этом низкоуровневого материал управления памятью, так что может быть что-то лучше.

+0

размер этой структуры является постоянным – tay10r

+0

Размер структуры никогда не меняется, это просто 'SizeOf (test_struct)'. Если вы хотите знать общую выделенную память, тогда да, вам также нужно будет делать 'num * sizeof (* values)'. –

+0

@Taylor Correct. Однако в буфере, который будет содержать его, должно быть выделено достаточно памяти для хранения 'values' Поэтому я вычисляю, как большие 'values' с' num * LENGTH', а затем добавляют размер самой 'struct'. – justynnuff

ответ

4

Если вы хотите memcpy две структуры, то память в обоих из них должна быть непрерывной. Но вам нужно будет заранее определить num.

struct test_struct { 
    int num; 
    char ** values; 
} * TestStruct; 

int _num = 0; 

// find _num 

TestStruct = malloc (sizeof (struct test_struct) + (sizeof(char*) * _num) + (LENGTH * _num)); 

TestStruct->num = _num; 
TestStruct->values = &TestStruct + sizeof (struct test_struct); 

for (int i = 0; i < _num; i++){ 
    TestStruct->values[i] = &TestStruct + sizeof (struct test_struct) + (i * LENGTH); 
} 

Причина Я изменил символ * на символ **, потому что, используя символ * становится все труднее получить доступ к строк после первого (я предполагаю, что они нулем). Кроме того, после вызова memcpy вы должны обновить все указатели строк в новой структуре.

Чтобы тетсру вы могли бы сделать это:

memcpy (buf, TestStruct->values[0], LENGTH * TestStruct->num); 

Но в BUF, однако, вы бы увидели только первую строку (если ваши строки не не завершается нулем). Вам нужно будет увеличивать указатель после каждого символа с нулевым завершением до тех пор, пока вы не узнаете, с num, что вы достигли конца буфера.


Теперь, когда я больше понимаю контекст вашего запроса, рассмотрим следующее.

Если вы используете UDP-пакеты, вы должны отправить данные в один пакет, чтобы он поступал в ожидаемом порядке. Когда отправляется более одного пакета, он может выйти из строя. Из-за этого вам необходимо убедиться, что размер данных < = 512 байт - это максимальный размер пакета UDP. Кроме того, вам необходимо убедиться, что все данные находятся в непрерывной памяти. Я буду считать, что у вас есть данные, которые уже в структуры предоставленной Вами в этом примере:

// this function puts the struct in contiguous memory 

int PrepareBuffer (struct test_struct TestStruct, char ** buffer){ 

    char * cast = (char *) &TestStruct->num; 

    * buffer = malloc ((TestStruct->num * LENGTH) + sizeof (int)); 

    for (int i = 0; i < sizeof (int); i++) *buffer[i] = cast[i]; 

    for (int i = 0; i < (TestStruct->num * LENGTH); i++) *buffer[i + sizeof (int)] = TestStruct->values[i]; 
    return 0; 
} 

Вы должны реализовать еще одну функцию на приемном конце, отображающей буфер struct test_struct. Кроме того, я пропустил проверку ошибок для ясности. Вы должны проверить, насколько большой будет пакет, чтобы выделить память (это должно быть < = 512) . Вы также должны убедиться, что malloc возвращает указатель none-null.

+0

Как вы получили 12? – Magn3s1um

+0

указатель имеет 8 байтов на 64-битной машине, а int, вероятно, 4. Это было просто предположение и может быть или не быть точным. – tay10r

+0

О, слово, мой разум мгновенно переходит к 32 бит – Magn3s1um

0

Необходимо выделить только 4 байта (для целого числа в 32-разрядном Linux) и 4 байта для символа char * (в 32-разрядном 64-битном формате - 8).

Что вы действительно спрашиваете, так как я знаю, сколько памяти мне нужно выделить в области, на которую указывает значение char *. Вы понимаете это в том, что вы делаете. Затем установите значение в местоположение buf. У меня есть комментарий, который будет правильным, если у вас есть несколько строк, и вы не хотите просто застревать их всех вместе в этом регионе и должны выяснить, что это такое.

0

Я предполагаю, что вы хотите выделить память как для структуры, так и для буфера, на который указывают значения. Если это так, это правильно. Для того, чтобы указать на дополнительное пространство, сделать buf->values = buf + 1; (это если вы объявляете БУФ, как struct test_struct buf;

+0

, этот ответ был получен из-за некоторого времени назад, но просто для того, чтобы уточнить 'buf-> values ​​= buf + 1' не указывает на дополнительное пространство, он указывает на смещенный байт' buf-> num' внутри структуры, которая переполнится в 'buf-> values'. Я думаю, что вы хотите написать «buf-> values ​​= & buf-> values ​​+ sizeof (char *);' – tay10r

+0

Я этого не делаю. В C добавление 1 к указателю на struct x добавляет sizeof (struct x), а не 1. Если вы добавляете 1 к указателю на char, вы действительно добавляете 1. Добавьте 1 к 32-разрядному целочисленному указателю, и вы фактически добавите 4! – DoxyLover

+0

ах, я столкнулся с этим в C++, но я не знал, что это началось на C. – tay10r

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