簡體   English   中英

如果realloc不能工作,但malloc可以嗎?

[英]How can realloc not work but malloc can?

我已經達到了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沒有分配時捕獲它將工作正常。 這引出了一個問題,mallocing我的數組而不是重新分配有什么問題導致進一步的問題?

我的數組是浮點指針的指針。 當我增長數組時,它將轉換為指向浮點數並重新分配的指針。 我在Android上構建,所以這就是為什么我認為缺乏內存。

從所有不同的信息位( realloc找不到內存, memcpy意外行為,崩潰)來判斷,這聽起來很像堆損壞。 如果沒有一些代碼樣本正是您正在做的事情,那么很難肯定地說,但似乎您在某些時候錯誤地管理了內存,導致堆進入無效狀態。

您是否能夠在Linux等備用平台上編譯代碼(您可能需要存根某些特定於Android的API)? 如果是這樣,你可以看到該平台上發生了什么和/或使用valgrind幫助追捕它。

最后,因為你有這個標記的C ++為什么你使用malloc / realloc而不是例如vector (或其他標准容器)或new

您會混淆size和指針類型。 在內存分配中, size是字節數,您將指針類型轉換為float * ,實質上是創建一個size size / sizeof(float)float數組。 在memcpy等效代碼中,您將數組視為float **並復制它們的size 這將廢棄堆,假設sizeof(float *) > 1 ,並且可能是后來問題的根源。

此外,如果您要將100個大小的數組復制到200個大小的數組,則需要復制超過100個元素,而不是200個。復制超出數組末尾(這是您正在做的)可以導致編程崩潰。

一個動態分配的float指針數組將是float **類型,而不是float * ,當然也不是兩者的混合。 數組的大小是malloc和friends的字節數,以及所有數組操作中的元素數。

memcpy將忠實地復制字節,假設源塊和目標塊不重疊(並且單獨分配的內存塊不重疊)。 但是,當復制的數字應該是舊數組的確切字節大小時,您已指定size - 1表示復制的字節數。 (無論如何,你在哪里得到糟糕的指針值?如果它在數組的擴展部分,你仍然在那里復制垃圾。)如果memcpy給你廢話,它開始是胡說八道,它不是你的問題。

順便說一下,你不需要測試array是否為NULL

你可以替換

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

通過

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

當給出NULL指針時, realloc就像malloc一樣。

另外一點,小心不要大小為0,因為大小為0的realloc與free相同。

第三點,當不是絕對必要不用強制轉換指針。 你斷言分配函數的返回,它被認為是ANSI-C以來的不良實踐。 它在C ++中是強制性的,但是當你使用C分配時,你顯然不是在C ++中(在這種情況下你應該使用new / delete )。 將數組變量轉換為(void *)也是不必要的,因為如果你的參數被錯誤地聲明它可能會隱藏一些警告(它可能是一個int或指向指針的指針,通過強制轉換你會抑制警告)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM