3

I am wondering how can I check an array is static or dynamically allocated. I looked up online and found the following implementation in mysql source code, I don't know why this works ? (line 0303 checks if the array is static)

       /*

0301     Just mark as empty if we are using a static buffer
0302   */
0303   if (array->buffer == (uchar *)(array + 1))
0304     array->elements= 0;

This is the definition of DYNAMIC_ARRAY in mysql :

341  
342 typedef struct st_dynamic_array
343 { 
344     uchar *buffer; 
345     uint elements,max_element; 
346     uint alloc_increment; 
347     uint size_of_element; 
348 } DYNAMIC_ARRAY; 
10
  • 4
    There is some missing context around those statements such as the definition and type of array. Commented Dec 23, 2015 at 3:20
  • 1
    Don't check. Just don't throw away the information in the first place. A good way to handle dynamic arrays is to use std::vector. Commented Dec 23, 2015 at 3:21
  • This is the definition of DYNAMIC_ARRAY in mysql : 341 342 typedef struct st_dynamic_array 343 { 344 uchar *buffer; 345 uint elements,max_element; 346 uint alloc_increment; 347 uint size_of_element; 348 } DYNAMIC_ARRAY; Commented Dec 23, 2015 at 3:23
  • @AliQajar can you link to the source you copied this from? Commented Dec 23, 2015 at 3:23
  • 1
    One cannot confirm whether a variable is static or dynamic without knowing more information, such as the address range of static memory or the range of addresses of dynamic memory. Then again, nothing is stopping the compiler from placing static variable next to dynamic variables. Commented Dec 23, 2015 at 3:26

3 Answers 3

3

You can't.

You're missing some context here. In this particular case, it's known that either array->buffer points to (uchar*)(array + 1) and is statically allocated, or it points somewhere else and is dynamically allocated.

But there's nothing about (uchar*)(array + 1) that automatically means something is statically allocated.

It's like asking how this function finds the length of the array (which is that it doesn't, unless the array ends with a 0):

int getArrayLength(int *a)
{
    for(int i = 0; ; i++)
        if(a[i] == 0)
            return i + 1;
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can't - without additional information.

For C, an array is just a bunch of memory addresses. a[n] actually means (type(a))*((void*)&a+n*sizeof(a)). It couldn't care less about how (or if) it was allocated, even whether the addresses are real.

The additional information may be:

  • the variable is of a specific type which has fields you can check for the information you want
    • this is your case: the code you supplied "knows" the variable is DYNAMIC_ARRAY
  • getting hints from the allocation system
    • e.g. free and realloc are only supposed to be called with pointers previously given by malloc. Checking a pointer's validity, however, isn't a part of the public interface
      • Debugging tools like valgrind, however, typically wrap the functions with a checker to validate the use of the routines

Comments

0

Just to explain what the mysql source code snippet is doing, which may help you.

Firstly it is not a test for statically allocated arrays. It attempts to test if an array and header were allocated contiguously ( one immediately following the other ).

if (array->buffer == (uchar *)(array + 1))
    array->elements= 0;

This is actually taking a pointer to the structure DYNAMIC_ARRAY and checks if the address of the array is pointing to the address immediately after the structure itself.

One way the test will be true is if the structure and array space were allocate in one single malloc() - a contiguous block. For example :

DYNAMIC_ARRAY *dap = NULL ;

dap = malloc( sizeof(DYNAMIC_ARRAY) + arraylength ) ;
dap->buffer = (uchar *)(dap+1) ;

This, IMO, is an unsafe piece of code, as it makes a dangerous assumption.

It assumes that two separate allocations, one of a header structure and one of array space, cannot follow each other in memory. This is outside of the control of the application, unless they've explicitly coded their own memory manager to not do that.

If this trick is being used elsewhere in the mysql sources I'd be quite alarmed, as it's just asking for trouble.

1 Comment

That was very informative. Now I see what is going on. The line that I copied was used a couple of times for memory management in array.c: it is accessible through the following link: osxr.org:8080/mysql/source/mysys/array.c

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.