我想知道如何检查数组是静态的还是动态分配的。我在网上查了一下,在mysql source code找到了以下实现,我不知道为什么会这样? (第0303行检查数组是否为静态)
/*
0301 Just mark as empty if we are using a static buffer
0302 */
0303 if (array->buffer == (uchar *)(array + 1))
0304 array->elements= 0;
这是mysql中DYNAMIC_ARRAY的定义:
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;
答案 0 :(得分: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 :(得分:1)
您无法提供其他信息。
对于C,数组只是一堆内存地址。 a[n]
实际上意味着(type(a))*((void*)&a+n*sizeof(a))
。即使地址是否真实,它也不会关心如何(或如果)分配它。
附加信息可能是:
DYNAMIC_ARRAY
free
和realloc
仅应使用先前由malloc
指定的指针进行调用。但是,检查指针的有效性并不是公共接口的一部分
valgrind
,但通常使用检查器包装函数以验证例程的使用答案 2 :(得分: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) ;
IMO这是一段不安全的代码,因为它是一个危险的假设。
它假定两个单独的分配,一个是头结构,另一个是数组空间,在内存中不能互相跟随。这超出了应用程序的控制范围,除非他们明确地将自己的内存管理器编码为不执行此操作。
如果在mysql源代码的其他地方使用这个技巧,我会非常惊慌,因为它只是在寻找麻烦。