C/C++:如何在运行时检查数组是静态的还是动态的

C/C++: How to check if an array is static or dynamic during runtime

我想知道如何检查数组是静态分配的还是动态分配的。我在网上查了一下 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;

这是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; 

你不能。

您在这里缺少一些上下文。 在这种特殊情况下,已知 array->buffer 指向 (uchar*)(array + 1) 并且是静态分配的, 它指向某处else 并且是动态分配的。

但是 (uchar*)(array + 1) 并没有自动意味着某些东西是静态分配的。

这就像问这个函数如何找到数组的长度(即它不会,除非数组以0结尾):

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

你不能 - 没有额外的信息。

对于C,数组就是一堆内存地址。 a[n]其实就是(type(a))*((void*)&a+n*sizeof(a))。它根本不关心它是如何(或是否)分配的,甚至地址是否真实。

附加信息可能是:

  • 该变量属于特定类型,其中包含您可以检查所需信息的字段
    • 这是你的情况:你提供的代码 "knows" 变量是 DYNAMIC_ARRAY
  • 从分配系统获取提示
    • 例如freerealloc 只能用之前由 malloc 给出的指针调用。但是,检查指针的有效性不是 public 接口的一部分
      • 然而,像 valgrind 这样的调试工具通常会用检查器包装函数以验证例程的使用

只是为了解释 mysql 源代码片段的作用,这可能对您有所帮助。

首先,它不是静态分配数组的测试。它尝试测试数组和 header 是否连续分配(一个紧接着另一个)。

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

这实际上是获取一个指向结构 DYNAMIC_ARRAY 的指针,并检查数组的地址是否指向结构本身之后的地址。

如果结构和数组 space 是在一个单独的 malloc() - 一个连续的块中分配的,则测试为真。例如:

DYNAMIC_ARRAY *dap = NULL ;

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

IMO,这是一段不安全的代码,因为它做出了危险的假设。

它假定两个单独的分配,一个 header 结构和一个数组 space,不能在内存中相互跟随。这不在应用程序的控制范围内,除非他们已经明确编码他们自己的内存管理器不这样做。

如果 mysql 来源中的其他地方使用了这个技巧,我会非常震惊,因为它只是在自找麻烦。