[英]memcpy extremely unexpected behavior
我正在使用memcpy在磁盤上寫入的數組中復制信息。 我要存儲一個256字節的char *(名稱數組)* , 3個長數字和一個短數字 。 我以為它可以正常工作,直到我嘗試了,但沒有成功。 將信息保存到磁盤時,一切似乎都可以正常工作。 但是,當嘗試讀取信息時,memcpy只會發生故障,將變量直接保留在名稱數組之后為0,並且當我的程序需要它來加載其他內容時,我會遇到段錯誤。
起初,我認為信息在寫入磁盤或從磁盤加載時可能已經損壞,但是我發現保存或加載過程沒有任何大問題,所以接下來要做的是打印出每個數組上的單個字節(使用Qt的qDebug),看看是否可以發現任何錯誤。
不用說,它不能按計划進行,因為qDebug僅打印非空字符,並且“名稱數組”有很多這樣的字符,但它卻出奇的令人驚訝:從某種意義上說,它使memcpy工作並且不工作它會成功復制第一個長號,但是會損壞第二個長號。 問題是,整個事情幾乎沒有關系!
char* block = new char[FreeBlock::TablaMTD_v]; //3958 bytes long
fRead.seekg(toLoad, ios::beg); //toLoad being an unsigned long file pointer, fRead being a working ifstream
fRead.read(block, FreeBlock::TablaMTD_v); //reading all 3958 bytes to block
fRead.close();
short bsize = 0, pos = 0;
memcpy(&bsize, block, 2);
pos+=2;
for(short i = 0; i < bsize; i++){
char* tname = new char[257];
unsigned long ptrmtd = 0, ptrdt = 0, ptrind = 0;
unsigned short indmtd = 0;
memcpy(tname, &block[pos], 256);
tname[256] = 0;
pos+=256;
memcpy(&ptrmtd, &block[pos], 8); //without qdebug loop, stays at 0. otherwise, has correct value
pos+=8;
memcpy(&ptrdt, &block[pos], 8); //with qdebug loop, stays at 0. otherwise, has correct value
pos+=8;
memcpy(&ptrind, &block[pos], 8);
pos+=8;
memcpy(&indmtd, &block[pos], 2);
pos+=2;
for(int i = 0; i < FreeBlock::TablaMTD_v; i++){
qDebug()<<block[i]; //miracle solution, somehow
}
CampoMTDB* cmtd = nextCampoMTDB(ptrmtd, true); //based on ptrmtd, which if 0, returns null pointer
unsigned long nextcmtdb = cmtd->next; //seg fault due to null pointer
因為那是我唯一添加的for循環,並且對其進行注釋/取消注釋實際上會改變整個過程的結果,所以我實在感到困惑。 排序為我在“意外行為”方面創下了新記錄。
考慮到我是C ++的新手,直到最近我聽說我在這里使用的隨機危險實踐顯然不應該使用,我仍然不知道如何或為什么在之后添加隨機for循環memcpy操作將對這些操作產生任何影響,或者為什么memcpy首先無法正常工作。
另請注意,保存文件后,我沒有再觸摸它,它完全沒有改變,但是讀取文件的輸出卻改變了。
以防萬一,我正在Qt 5.3,x64 Windows 7中使用VC2013
由於您在Windows 7下使用VC2013,因此unsigned long
的大小為4個字節(而不是8個字節)。
在任何情況下,為了您自己的安全,都應使用sizeof
而不是那些常數8和2。
更改此:
memcpy(&ptrmtd, &block[pos], 8);
pos+=8;
memcpy(&ptrdt, &block[pos], 8);
pos+=8;
memcpy(&ptrind, &block[pos], 8);
pos+=8;
memcpy(&indmtd, &block[pos], 2);
pos+=2;
對此:
memcpy(&ptrmtd, &block[pos], sizeof(ptrmtd));
pos+=sizeof(ptrmtd);
memcpy(&ptrdt, &block[pos], sizeof(ptrdt));
pos+=sizeof(ptrdt);
memcpy(&ptrind, &block[pos], sizeof(ptrind));
pos+=sizeof(ptrind);
memcpy(&indmtd, &block[pos], sizeof(indmtd));
pos+=sizeof(indmtd);
由於系統上的sizeof(unsigned long) == 4
,因此memcpy(&ptrmtd, &block[pos], 8);
可以修改不是您的內存。 這是非常危險的,所以永遠不要這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.