简体   繁体   中英

memcpy extremely unexpected behavior

I'm using memcpy to copy information from and to an array that is getting written on disk. I'm storing a char* of 256 bytes (name array)* , 3 long numbers , and a short number . 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.

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.

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. 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. 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.

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

Since you're using VC2013 under Windows 7, the size of unsigned long is 4 bytes (not 8 bytes).

And in any case, for your own safety, you should use sizeof instead of those constant values of 8 and 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); can modify memory that is not yours. It is very dangerous, so never do it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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