看板 C_and_CPP 關於我們 聯絡資訊
原來的作法是: int **data; data = (int**)new char [height * sizeof(int *) + width * height * sizeof(int)]; for (i = 0; i < height; i++) data[i] = (int *)data + height + i * width; 其中這一行 data[i] = (int *)data + height + i * width; 在64位元的電腦應該會造成記憶體出問題,假設sizeof(int)是4而sizeof(int*)是8, (int*)data+1和(int*)(data+1)是不一樣的。 前者加sizeof(int)後者加sizeof(int*) ,因為data是int**。 所以可以考慮改成: data[i] = (int*)data + height*(sizeof(int*)/sizeof(int)) + i * width; 另一種作法,利用sizeof(char)是一個byte: ddata[i] = (int*)((char*)(data + height) + i * width * sizeof(int)); 總而言之,記憶體爬格子是個需要小心的工作... 越來越多電腦買來的時候就是裝64位元的,所以這類的狀況應該滿容易碰到。 另外一件事就是,記憶體配置錯誤還是可能寫值進去,而且電腦沒報錯。 可能的原因包括測試的迴圈被最佳化忽略掉,或者剛好被覆寫的記憶體沒被使用等。 這些只是根據原PO提供的資訊所作的猜測,如果code原本已經是正確寫法, 或者確定coding的環境沒有這個問題,那可以直接忽略我這一篇。 -- 謝謝uranusjr提供的highlighter http://bbshighlighter.uranusjr.com/ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 111.249.181.204
yvb:若是64位元電腦,可能是發生資料錯亂,而不是堆積損毁程式掛掉; 03/18 18:37
yvb:反而是32位元電腦搭上double,造成後面資料讀超出配置範圍掛掉. 03/18 18:38
dirkc:不知道yvb說的堆積損和資料錯亂的差別?不過在我x64 linux上 03/18 21:36
dirkc:是segmentation fault,遞迴data[x]就會寫到錯誤位址了 03/18 21:38
dirkc:再deref就會seg fault 03/18 21:38
dirkc:雖然用debugger就可以,我還是寫了一個測試 03/18 22:08
dirkc:http://ideone.com/7Xybus 03/18 22:08
dirkc:阿遞迴應該說迭代,錯誤中文用詞 03/18 22:29
yvb:抱歉, 一時沒想清楚, 以為64位元搭配int只是指標指的範圍太小, 03/19 12:44
yvb:在data內重疊, 可能重覆蓋寫資料, 造成資料錯亂而已; 沒考慮到 03/19 12:45
yvb:讀取資料時, 會蓋寫到 data[i], 而可能讓 data[i] 指向錯誤; 03/19 12:45
yvb:當然, 若運氣超好, 讀進 (&data[i]) 的資料值恰巧指向合法位址 03/19 12:45
yvb:也可能純粹搞亂資料而已, 而未造成 segfault. 03/19 12:46
yvb:相對32位元搭配double, 則是在設定 data[i] 指標時就超出範圍; 03/19 12:46
yvb:但如果在讀入 data 前又額外配置記憶體, 也可能後續的讀取只是 03/19 12:46
yvb:蓋寫後來配置區域的資料, 而不會發生 segfault. 03/19 12:47
yvb:至於堆積損毁, 其實是原PO附圖中的詞, 也就是heap corruption, 03/19 12:47
yvb:有幾種情況, 其中之一就是指標錯誤又去存取資料而發生的. 03/19 12:48