我非常意外的行为
memcpy extremely unexpected behavior
我使用memcpy将信息从一个正在写入磁盘的数组中复制到这个数组中。我存储一个256字节的char*(名称数组)*, 3个长数字,和一个短数字。我以为它会正常工作,直到我尝试了它,它没有。将信息保存到磁盘时,一切似乎都很正常。但是,当试图读取信息时,memcpy就会出现故障,将变量直接留在名称数组后面为0的位置,当我的程序需要它来加载其他内容时,就会出现segfault。
起初我认为当写入磁盘时,信息可能已经损坏,或者当从它加载时,但我找不到保存或加载过程的任何大问题,所以我接下来做的是打印出数组上的每一个字节(与Qt的qDebug),看看我是否能发现任何错误。
不用说,它没有按计划工作,因为qDebug只打印非空字符,而"name数组"有很多这样的字符,但它做了一些令人惊讶的事情:它以某种方式使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++有点陌生,直到最近我才听说我在这里使用的随机危险实践显然是我不应该使用的,我仍然不明白在memcpy操作之后添加随机for循环如何或为什么会对这些操作产生任何影响,或者为什么memcpy一开始就不能像它应该的那样工作。
还请注意,在我保存文件之后,我没有再碰它,它根本没有改变,但是读取它的输出改变了。
如果它有助于知道,我在Qt 5.3中使用VC2013, x64 Windows 7
由于您在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);
可以修改不属于您的内存。这是非常危险的,所以千万不要这样做。
- 在C++中对T*类型执行std::move的意外行为
- OpenGL大的3D纹理(>2GB)非常慢
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 处理除以零会导致<csignal>意外行为
- vscode下的Arduino代码出现意外编译错误
- 使用++运算符会导致意外的结果
- 套接字读取后,我在缓冲区中看到意外输入
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 使用vscode调试时,GDB意外退出
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- G++ C++17 类模板参数推导在非常特殊的情况下不起作用
- 尝试将字符串/字符转换为整数会产生意外结果
- 使用浮点数和双精度数的非常小数字的数学
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- C++标头错误 C2238 意外标记";"
- C++中意外的多头值
- 我非常意外的行为
- 非常基本的c++程序中的意外输出