C / C ++如何知道动态分配的数组有多长

时间:2011-03-11 01:44:28

标签: c++ python c memory-management dynamic-memory-allocation

这个问题困扰了我一段时间。

例如,如果我做int* a = new int[n],我只有一个指向数组a开头的指针,但C / C ++如何知道n?我知道如果我想将这个数组传递给另一个函数,那么我必须用它传递数组的长度,所以我猜C / C ++并不知道这个数组有多长。

我知道我们可以通过查找NUL终结符来推断字符数组char*的结尾。但其他数组是否有类似的机制,比如int?同时,char可以不仅仅是一个字符 - 您也可以将其视为整数类型。那么C ++如何知道这个数组的结束呢?

当我开发嵌入式Python时,这个问题开始让我更加困扰(如果你不熟悉嵌入式python,你可以忽略这一段并回答上面的问题。我仍然会欣赏它)。在Python中有一个“ByteArray”,将“ByteArray”转换为C / C ++的唯一方法是使用PyString_AsString()将其转换为char *。但是如果这个ByteArray中有0,那么C / C ++会认为char *数组会提前停止。这不是最糟糕的部分。最糟糕的是,比方说我做了

char* arr = PyString_AsString(something)
void* pt = calloc(1, 1000); 

如果st恰好从0开始,那么C / C ++几乎可以保证消灭arr中的所有内容,因为它认为arr在出现NULL之后就会结束。然后它可能只是通过为pt分配一个内存树干来消灭arr中的所有内容。

非常感谢你的时间!对此,我真的非常感激。

3 个答案:

答案 0 :(得分:7)

C / C ++没有;它是 allocator (实现malloc()free()等的一小段代码),它知道它有多长。欢迎使用C / C ++,不受担心长度的限制。

另外,PyString_AsStringAndSize()

答案 1 :(得分:4)

让我们击中反汇编程序!对于C和C ++,这将是不同的。 free如何在C中工作的问题在另一个问题中有所涉及,以及它在C ++中的工作原理:

struct T {
    ~T();
    int data;
};
void test(T* p)
{
    delete[] p;
}

让我们运行编译器来生成程序集。这是为i386编译的相关位:

    movl    -4(%edi), %eax
    leal    (%edi,%eax,4), %esi
    cmpl    %esi, %edi
    je      L4
    .align 4,0x90
L8:
    subl    $4, %esi
    movl    %esi, (%esp)
    call    L__ZN1TD1Ev$stub
    cmpl    %esi, %edi
    jne     L8

你可以看到重要的部分:在p开始之前存在一个整数,其中包含p的长度,然后代码在p数组上循环,调用数组中每个项的析构函数。然后调用delete,这通常很无聊,因为它只调用free(C函数)。因此,您可以看到C ++ delete如何用free表示。

析构函数和异常:基于上面的程序集,您可以注意到如果T的析构函数抛出异常,那么部分p数组将获得析构函数被调用,而数组的其余部分则不会。析构函数永远不应该抛出异常。

警告:这只是编译器和运行时可以解决此问题的一种可能方式。 (这里,析构函数由编译器生成的代码调用,而delete是运行时的一部分。)这些实现方式有很大的余地,而你的可能会有所不同。这也说明了为什么你应该总是调用正确的运算符delete[]delete - 调用错误的运算符会导致各种麻烦,例如踩踏内存并释放无效指针。

关于NUL终结符: NUL终止符出问题的唯一原因是PyString_AsString和其他类似函数调用strlen来计算字符串的长度。但是,free并不关心NUL终结符,相反,它会分别跟踪原始malloc调用的长度。对于PyString_AsString(以及strdup等),这不是一个选项,因为没有可移植的方式来获取内存区域的大小 - mallocfree不要公开此功能。此外,您可以将指针传递给位于PyString_AsString块中间或完全位于其他位置的malloc

答案 2 :(得分:0)

c / c ++不知道任何数组的长度,因此您可以轻松跨界访问数组。 c / c ++也不知道char数组的长度。

Char *可以指向字符串,但它不等于字符串。以NULL结尾的字符串是c / c ++的约定。