2015-12-23 3 views
2

Мне интересно, как я могу проверить, что массив статичен или динамически распределен. Я посмотрел онлайн и нашел следующую реализацию в mysql source code, я не знаю, почему это работает? (строка 0303 проверяет, является ли массив является статическим)C/C++: Как проверить, является ли массив статическим или динамическим во время выполнения

 /* 

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

Это определение DYNAMIC_ARRAY в 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; 
+4

Существует некоторый недостающий контекст вокруг этих утверждений, таких как определение и тип 'array'. –

+1

Не проверять. Просто не выбрасывайте информацию в первую очередь. Хорошим способом обработки динамических массивов является использование 'std :: vector'. –

+0

Это определение DYNAMIC_ARRAY в mysql: 342 typedef struct st_dynamic_array 343 { 344 uchar * buffer; 345 элементов uint, max_element; 346 uint alloc_increment; 347 uint size_of_element; 348} DYNAMIC_ARRAY; –

ответ

3

Вы не можете.

Вам не хватает контекста здесь. В данном конкретном случае известно, что либо array->buffer указывает на (uchar*)(array + 1) и статически выделяется, или указывает на то, что находится где-то в другом месте и динамически выделяется.

Но ничего не найдено о (uchar*)(array + 1), что автоматически означает, что что-то статически распределено.

Это как спрашивать, как эта функция находит длину массива (который является то, что это не, если массив не заканчивается с 0):

int getArrayLength(int *a) 
{ 
    for(int i = 0; ; i++) 
     if(a[i] == 0) 
      return i + 1; 
} 
1

Вы не можете - без дополнительного Информация.

Для C массив - это всего лишь куча адресов памяти. a[n] на самом деле означает (type(a))*((void*)&a+n*sizeof(a)). Ему было все равно, как (или если) он был выделен, даже если адреса являются реальными.

Дополнительная информация может быть:

  • переменных определенного типа, который имеет поле, которые вы можете проверить информацию, которую вы хотите
    • это ваш случай: код поставки «знает "переменная DYNAMIC_ARRAY
  • получать подсказки от системы распределения
    • , например. free и realloc должны быть вызваны только указателями, заданными ранее malloc. Проверка валидности указателя, однако, не является частью открытого интерфейса
      • Отладочных средств, как valgrind, однако, как правило, обернуть функции с проверкой для проверки использования подпрограмм
0

Просто объясните, что делает фрагмент кода mysql, который может вам помочь.

Во-первых, это не тест для статически распределенных массивов. Он пытается проверить, был ли массив и заголовок распределены смежно (один сразу после другого).

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

Это на самом деле принимает указатель на структуру DYNAMIC_ARRAY и проверяет, если адрес массива указывает на адрес сразу после самой структуры.

Один из способов проверки будет истинным, если структура и пространство массива были выделены в одном malloc() - непрерывном блоке. Например:

DYNAMIC_ARRAY *dap = NULL ; 

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

Это, ИМО, является небезопасным кодом, поскольку это делает опасное предположение.

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

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

+0

Это было очень информативно. Теперь я вижу, что происходит. Скопированная строка использовалась пару раз для управления памятью в array.c: она доступна по следующей ссылке: http://osxr.org:8080/mysql/source/mysys/array.c –