简体   繁体   English

memcpy极其意外的行为

[英]memcpy extremely unexpected behavior

I'm using memcpy to copy information from and to an array that is getting written on disk. 我正在使用memcpy在磁盘上写入的数组中复制信息。 I'm storing a char* of 256 bytes (name array)* , 3 long numbers , and a short number . 我要存储一个256字节的char *(名称数组)*3个长数字一个短数字 I thought it was going to work correctly until I tried it and it didn't. 我以为它可以正常工作,直到我尝试了,但没有成功。 When saving the information to disk, everything seems to work just fine. 将信息保存到磁盘时,一切似乎都可以正常工作。 But when trying to read off the information, memcpy simply malfunctions, leaving the variable directly after the name array at 0, and when my program needs it to load up something else, I end up with a seg fault. 但是,当尝试读取信息时,memcpy只会发生故障,将变量直接保留在名称数组之后为0,并且当我的程序需要它来加载其他内容时,我会遇到段错误。

At first I thought the information could've been getting corrupted when written to disk, or when being loaded from it, but I couldn't find any huge issues with the saving or loading procedures, so what I did next was to print out every single byte on the array (with Qt's qDebug), see if I could spot anything wrong with it. 起初,我认为信息在写入磁盘或从磁盘加载时可能已经损坏,但是我发现保存或加载过程没有任何大问题,所以接下来要做的是打印出每个数组上的单个字节(使用Qt的qDebug),看看是否可以发现任何错误。

Needless to say, it didn't work out as planned since qDebug only printed non null characters, and the "name array" has a lot of those, but it did something ridiculously surprising: it somehow made memcpy work and not work, since now it would successfully copy the first long number, but it would then corrupt the second long number. 不用说,它不能按计划进行,因为qDebug仅打印非空字符,并且“名称数组”有很多这样的字符,但它却出奇的令人惊讶:从某种意义上说,它使memcpy工作并且不工作它会成功复制第一个长号,但是会损坏第二个长号。 Thing is, the whole thing is pretty much unrelated! 问题是,整个事情几乎没有关系!

            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

Since that for loop is the only thing I have added, and commenting it/uncommenting it actually changes the outcome of the entire procedure, I'm quite honestly baffled. 因为那是我唯一添加的for循环,并且对其进行注释/取消注释实际上会改变整个过程的结果,所以我实在感到困惑。 Sort of sets a new record for me on the "unexpected behavior" plane. 排序为我在“意外行为”方面创下了新记录。

Taking into consideration I'm somewhat new to C++, and I've until recently heard of random dangerous practices I'm using here that apparently I should not be using, I still don't see how or why adding a random for loop AFTER memcpy operations would have any impact whatsoever on these operations, or why memcpy wouldn't work like it should in the first place. 考虑到我是C ++的新手,直到最近我听说我在这里使用的随机危险实践显然不应该使用,我仍然不知道如何或为什么在之后添加随机for循环memcpy操作将对这些操作产生任何影响,或者为什么memcpy首先无法正常工作。

Also note that after I saved my file, I didn't touch it again, it hasn't changed at all, yet the output from reading it changes. 另请注意,保存文件后,我没有再触摸它,它完全没有改变,但是读取文件的输出却改变了。

In case it helps to know, I'm using VC2013 in Qt 5.3, x64 Windows 7 以防万一,我正在Qt 5.3,x64 Windows 7中使用VC2013

Since you're using VC2013 under Windows 7, the size of unsigned long is 4 bytes (not 8 bytes). 由于您在Windows 7下使用VC2013,因此unsigned long的大小为4个字节(而不是8个字节)。

And in any case, for your own safety, you should use sizeof instead of those constant values of 8 and 2. 在任何情况下,为了您自己的安全,都应使用sizeof而不是那些常数8和2。

Change this: 更改此:

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;

To this: 对此:

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);

Since sizeof(unsigned long) == 4 on your system, memcpy(&ptrmtd, &block[pos], 8); 由于系统上的sizeof(unsigned long) == 4 ,因此memcpy(&ptrmtd, &block[pos], 8); can modify memory that is not yours. 可以修改不是您的内存。 It is very dangerous, so never do it. 这是非常危险的,所以永远不要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM