memcpy非常意外的行为

时间:2014-06-24 11:03:21

标签: c++

我正在使用memcpy将信息复制到正在写入磁盘的数组中。我正在存储 256字节的char *(名称数组)* 3长数短数。我认为它会正常工作,直到我尝试它并没有。将信息保存到磁盘时,一切似乎都运行正常。但是当试图读取信息时,memcpy只是出现故障,将变量直接留在名称数组后面的0,当我的程序需要加载其他内容时,我最终会出现seg错误。

起初我认为这些信息在写入磁盘时或者从磁盘上加载时可能已经损坏了,但我找不到保存或加载程序的任何大问题,所以我接下来要做的就是打印出阵列上的每个字节(使用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

2 个答案:

答案 0 :(得分:3)

由于您在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);

答案 1 :(得分:0)

自系统sizeof(unsigned long) == 4起,memcpy(&ptrmtd, &block[pos], 8);可以修改不属于您的内存。这是非常危险的,所以永远不要这样做。