2008-12-11 3 views
0

Это довольно простой вопрос, который по какой-то причине убеждает меня в правильном решении. Я имею дело с третьей стороной SDK, который декларирует следующую структуру:Как хранить данные в массивах переменной длины без повреждения памяти?

struct VstEvents 
{ 
    VstInt32 numEvents; ///< number of Events in array 
    VstIntPtr reserved; ///< zero (Reserved for future use) 
    VstEvent* events[2]; ///< event pointer array, variable size 
}; 

Несмотря на то, что это «переменный размере» массив, он статический объявлен. Поэтому, очевидно, если я создаю объект VstEvents, задайте значение numEvents, а затем перейдите и начните добавлять их в массив, это приведет к повреждению памяти.

Так как же я должен правильно разбираться с такой структурой? Должен ли я выделить свой собственный массив VstEvent *, а затем указать на него события [0]?

ответ

0

Если вы знаете, сколько вы можете выделить его с

struct VstEvents *evnts; 

evnts = (struct VstEvents*)malloc(sizeof(struct VstEvents) + 
            numEvents*sizeof(VstEvent*)); 

Это выделит 2 дополнительные слотов

+0

В C нельзя отбрасывать возвращаемое значение из malloc(). Это может скрыть ошибку. – unwind 2008-12-11 12:19:57

+0

Это верно только в C89. В C99 вы не можете использовать декларации неявных функций, поэтому не имеет значения, вы или нет. Кастинг делает код компилируемым под C++. – 2008-12-13 06:48:22

-1

Что структура объявляет массив (размер 2) указателей к объектам VstEvent. Вы должны выделить VstEvent и назначить его событиям [0], установив numEvents в 1. Если у вас есть 2 VstEvents, выделите еще один VstEvent, назначьте ему события [1] и установите numEvents на 2. Если вам нужно больше, чем 2 , то вам нужно будет сделать realloc на VstEvents, чтобы увеличить его размер, чтобы события содержали количество указателей, которые вам нужны, и назначать 2, 3, 4, ... по мере необходимости. Или, если вы заранее знаете, сколько событий вам нужно будет хранить, вы можете выделить его изначально, как показывает @ SDX2000.

Я думаю, что основная идея состоит в том, что они объявляют его с размером 2 для удобства, так что если у вас только 1 или 2, вам не нужно делать дополнительный malloc для измерения массива событий.

3

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

struct VstEvents 
{ 
    VstInt32 numEvents; ///< number of Events in array 
    VstIntPtr reserved; ///< zero (Reserved for future use) 
    VstEvent* events[2]; ///< event pointer array, variable size 
}; 

#define numEventsRequired 10 
VstEvents *vstEvents = (VstEvents*)malloc(sizeof(VstEvents) + sizeof(VstEvents*)*(numEventsRequired-2)); 

vstEvents->numEvents = numEventsRequired; 
0

Ваша библиотека третьей стороной является немного странным. Вы должны различать два вида «массивов переменного размера»

  • Размер известно, когда массив выделяется и никогда не меняется после. Это простой случай, и я показываю идиому C99 ниже.

  • Окончательный размер неизвестно, когда массив выделяется и массив, возможно, придется расти в течение своей жизни. Для чего-то подобного я бы рекомендовал вам проверить реализацию Seq_T в исходном файле seq.c в C Interfaces and Implementations Дейва Хэнсона. Вы можете легко адаптировать свой код.

Если вы знаете размер на время размещения C99 идиома заключается в следующем:

struct VstEvents 
{ 
    VstInt32 numEvents; ///< number of Events in array 
    VstIntPtr reserved; ///< zero (Reserved for future use) 
    VstEvent* events[]; ///< event pointer array, variable size 
}; 


struct VstEvents *alloc_vst_events(int num_events) { 
    struct VstEvents *p = 
      malloc(sizeof(*p) + num_events * sizeof(p->events[0])); 
    return p; 
} 

Ключ в том, что странно массив в структуры с размером не указывать. Требуется C99.

Поскольку вы застряли с 3-й партии странности Я хотел бы попробовать это:

#define NELEMS(A) (sizeof(A)/sizeof((A)[0])) 

struct VstEvents *alloc_vst_events(int num_events) { 
    struct VstEvents *p; 
    int events_needed = num_events - NELEMS(p->events); 
    p = malloc(sizeof(*p) + events_needed * sizeof(p->events[0])); 
    return p; 
} 

Отказ от ответственности: Я не отодвигают этот код через компилятор. Исправления приветствовали.

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