[英]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.