1

我已经到了 realloc 停止返回指针的地步——我假设数组没有空间来扩展或移动。唯一的问题是我真的需要该内存存在或应用程序无法按预期运行,所以我决定尝试 malloc - 期待它不起作用,因为 realloc 不起作用 - 但它确实如此。为什么?

然后我将指针数组memcpy到新分配的数组中,但发现它破坏了它,像0x10和0x2b这样的指针被放入了数组中。有真正的指针,但如果我用 for 循环替换 memcpy,就可以修复它。为什么 memcpy 这样做?我不应该在我的代码中使用 memcpy 吗?

代码:

float * resizeArray_by(float *array, uint size)
{
    float *tmpArray = NULL;
    if (!array)
    {
        tmpArray = (float *)malloc(size);
    }
    else
    {
        tmpArray = (float *)realloc((void *)array, size);
    }

    if (!tmpArray)
    {
        tmpArray = (float *)malloc(size);
        if (tmpArray)
        {
            //memcpy(tmpArray, array, size - 1);
            for (int k = 0; k < size - 1; k++)
            {
                ((float**)tmpArray)[k] = ((float **)array)[k];
            }
            free(array);
        }
    }

    return tmpArray;
}

void incrementArray_andPosition(float **& array, uint &total, uint &position)
{
    uint prevTotal = total;
    float *tmpArray = NULL;
    position++;
    if (position >= total)
    {
        total = position;
        float *tmpArray = resizeArray_by((float *)array, total);
        if (tmpArray)
        {
            array = (float **)tmpArray;

            array[position - 1] = NULL;
        }
        else
        {
            position--;
            total = prevTotal;
        }
    }
}

void addArray_toArray_atPosition(float *add, uint size, float **& array, uint &total, uint &position)
{
    uint prevPosition = position;
    incrementArray_andPosition(array, total, position);

    if (position != prevPosition)
    {
        float *tmpArray = NULL;
        if (!array[position - 1] || mHasLengthChanged)
        {
            tmpArray = resizeArray_by(array[position - 1], size);
        }

        if (tmpArray)
        {
            memcpy(tmpArray, add, size);
            array[position - 1] = tmpArray;
        }
    }
}

经过我所有的修复后,代码可能会初始化。这里有趣的是,在对数组进行排序之后,我用 malloc 分配了一个巨大的数组,因此将这些数组重新排序为一个数组以用作 GL_ARRAY_BUFFER。如果 realloc 由于空间不足而没有分配,那么为什么不分配呢?

最后,这导致它最终崩溃。在通过渲染功能后一旦它崩溃。如果我删除了所有修复程序并在 realloc 未分配时被捕获,它会正常工作。这就引出了一个问题,分配我的数组而不是重新分配以进一步导致问题进一步有什么问题?

我的数组是浮点指针的指针。当我增大数组时,它会转换为指向浮点数并重新分配的指针。我在 Android 上构建,所以这就是我认为内存不足的原因。

4

3 回答 3

3

从所有不同的信息位(realloc找不到内存、memcpy行为异常、崩溃)来看,这听起来很像堆损坏。如果没有一些代码示例确切地说明您正在做什么,很难确定,但似乎您在某些时候对内存管理不当,导致堆进入无效状态。

您是否能够在 Linux 等替代平台上编译您的代码(您可能需要存根一些 android 特定的 API)?如果是这样,您可以查看该平台上发生的情况和/或使用 valgrind 来帮助追捕它。

最后,既然你有这个标记的 C++ 为什么你使用 malloc/realloc 而不是,例如,vector(或另一个标准容器)或new

于 2011-05-10T14:42:13.353 回答
1

您对size指针类型感到困惑。在内存分配中,size是字节数,您将指针类型转换为,本质上是创建一个大小float *为 的数组。在 memcpy 等效代码中,您将数组视为并复制它们。这将破坏堆,假设, 并且可能是以后问题的根源。floatsize / sizeof(float)float **sizesizeof(float *) > 1

此外,如果您将 100 大小的数组复制到 200 大小的数组,则需要复制超过 100 个元素,而不是 200 个。复制超出数组末尾(这就是您正在做的事情)可能会导致程序崩溃。

一个动态分配的指向floats 的指针数组的类型是float **,不是float *,当然也不是两者的混合。数组的大小是分配给 malloc 和朋友的字节数,以及所有数组操作中的元素数。

memcpy假设源块和目标块不重叠(并且单独分配的内存块不重叠),将忠实地复制字节。但是,您已经指定size - 1了复制的字节数,当复制的数字应该是旧数组的确切字节大小时。(无论如何,你在哪里得到错误的指针值?如果它在数组的扩展部分,那么无论如何你都在复制垃圾。)如果memcpy给你废话,那么一开始就是废话,这不是你的问题.

于 2011-05-10T15:40:19.197 回答
0

顺便说一句,你不需要测试是否arrayNULL

你可以更换

if (!array)
{
    tmpArray = (float *)malloc(size);
}
else
{
    tmpArray = (float *)realloc((void *)array, size);
}

经过

tmpArray = realloc(array, size*sizeof (float));

realloc就像malloc给定NULL指针时一样。

另一件事,注意 size 不是 0,因为 realloc 与 0 一样 size 与 free.

第三点,不要在非绝对必要时对指针进行类型转换。您对分配函数的返回进行了类型转换,自 ANSI-C 以来,这被认为是不好的做法。它在 C++ 中是强制性的,但是当您使用 C 分配时,您显然不在 C++ 中(在这种情况下,您应该使用new/ delete)。将数组变量强制转换为 (void *) 也是不必要的,因为如果您的参数被错误地声明(它可能是一个 int 或指向指针的指针,并且通过强制转换您会抑制警告),它可能会隐藏一些警告。

于 2011-05-10T17:07:57.593 回答