How to store data in variable length arrays without corrupting memory?

This is a fairly simple question, which for some reason in my opinion speeds up the solution. I am dealing with a third party SDK that declares the following structure:

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

      

Even though it is a variable-sized array, it was declared statically. So obviously if I create a VstEvents object, set the value to numEvents and then go ahead and start adding them to the array, it will cause memory corruption.

So how am I supposed to properly deal with such a structure? Should I allocate my own VstEvent * array and then point to events [0]?

+1


source to share


4 answers


If you know how much there is, you can highlight it with

struct VstEvents *evnts;

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

      



This will allocate 2 additional slots

+1


source


you need to pre-allocate a chunk of memory big enough to hold the whole thing + any additional entries you want ...



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(VstEvent*)*(numEventsRequired-2));

vstEvents->numEvents = numEventsRequired;

      

+4


source


Your third party library is a little weird. You need to distinguish between the two types of "variable sized arrays"

  • The size is known when the array is allocated and never changes thereafter . This is a simple case and I am showing the C99 idiom below.

  • The final size is unknown when the array is allocated and that may be required to create the array for its entire life. For something like this, I would recommend you check out the implementation of Seq_T in the seq.c source file in Dave Hanson C Interfaces and Implementations . You can easily adapt its code.

If you know the size at allocation time, the C99 idiom is:

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;
}

      

The key is that there is a strange array in a structure with a size left unspecified. Requires C99.

Since you are stuck in a weird weirdness, I would try this:

#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;
}

      

Disclaimer: I did not run this code through the compiler . Bug fixes.

0


source


What the structure declares is an array (size 2) of pointers to VstEvent objects. You should allocate VstEvent and assign it to events [0] by setting numEvents to 1. If you have 2 VstEvents, allocate another VstEvent, assign events [1] to it and set numEvents to 2. If you need more than 2, then you will need to do realloc on VstEvents to increase its size so that events contain the number of pointers you need and assign 2, 3, 4, ... as needed. Or, if you know in advance how many events you will need to store, you can allocate it initially, as @ SDX2000 shows.

I think the basic idea is that they declare it with size 2 for convenience, so if you only have 1 or 2, you don't need to do extra malloc to measure the event array.

-1


source







All Articles