memcpy not copying

Started by
21 comments, last by Spoonbender 16 years, 8 months ago
Hiya :) Could anyone explain me how this is possible:

// assuming pDest, pSrc and size are all valid
memcpy(pDest, pSrc, size)
assert( memcmp(pDest, pSrc, size) == 0 ) // ASSERTION FAILS !
The platform is Windows XP 64bit edition. Any clue would be (god damn) appreciated [smile] Regards, JA Edit: whoooooho looks like I forgot a fundamental thing. I'm gonna check whether my pointers overlap...
Advertisement
Have you stepped through with a debugger?

Looked at the generated assembly?

I wouldn't hazard a guess without both of these things
I've been stepping through assembly code all day [smile]
I've done more debugging. Both pointers are perfectly valid, the byte count is valid. There is no overlap.

Ok, here's my code. I cant believe what I'm seing. Either I'm very stupid, or I'm very tired, or very cursed [smile]

template <class T> T* Duplicate( const T* pObj, int numObjects){	T *pNewObj = new T[numObjects];	memcpy( pNewObj, pObj, bytes );	return pNewObj;};


In order to to debug, I did this:

template <class T> T* Duplicate( const T* pObj, int numObjects){    T *pNewObj = new T[numObjects];    u32 bytes = sizeof(T) * numObjects;    memcpy( pNewObj, pObj, bytes );    // detect differences    if( memcmp(pNewObj, pObj, bytes ) )    {        _asm int 3;        // find out what is different        for(u32 i = 0 ; i < bytes ; ++i)	{            if(pSource != pDest)		__asm int 3;	}        // give it another try	memcpy( pNewObj, pObj, bytes );        // Still not good ???	if( memcmp(pNewObj, pObj, bytes ) )	{	    _asm int 3;	    for(u32 i = 0 ; i < bytes ; ++i)	    {	        if(pSource != pDest)		    __asm int 3;	    }	}		    }        return pNewObj;};


After the first memcpy, sometimes the memcmp will detect a difference. The small loop right after that always tells me that all the bytes are identical EXCEPT 4 adjacent bytes (as if someone had written a int = 0 to the data, forming a "hole") Everything before and after that hole is identical to the source buffer. The offset of that hole from the begining of the buffer may vary, and is no special value. The next memcpy (second attempt) always fills the hole and no further differences are detected...

This is so damn weird, and I'm prety sure it must be something stupid I just overlooked...

The very same executable file generates no such error under Windows xp 32bit, only under Windows xp 64bits (but that could be a coincidence)
template <class T> T* Duplicate( const T* pObj, int numObjects){	T *pNewObj = new T[numObjects];	memcpy( pNewObj, pObj, bytes );	return pNewObj;};


Where is "bytes" coming from? Mars? [smile]

[EDIT] AH... I see you fixed that down lower.

Well... this sounds like some type of CRT library mismatch to me... something built against a static library (of your own) that is out of date, that type of thing.
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Is there a reason why you aren't using std::copy? Or something like this:

template <typename T>std::vector<T> Duplicate(const std::vector<T>& objects){    return std::vector<T> ret(objects);}
Quote:Original post by Verg
template <class T> T* Duplicate( const T* pObj, int numObjects){	T *pNewObj = new T[numObjects];	memcpy( pNewObj, pObj, bytes );	return pNewObj;};


Where is "bytes" coming from? Mars? [smile]

[EDIT] AH... I see you fixed that down lower.

Well... this sounds like some type of CRT library mismatch to me... something built against a static library (of your own) that is out of date, that type of thing.


The game is built under Windows XP 32bit with the Multi-Threaded DLL (/MD)

if I replace the memcpy by a loop of my own, everything is just fine

for(u32 i = 0 ; i < bytes ; ++i)    pDest = pSource;


@Driv3MeFar: Yeah there is. I'm not coding at home, I'm working on a large codebase like 1M lines of code and I cant afford to refactor everything. The team who originally designed the software made the choice not to use stl.



Quote:Original post by janta
Quote:Original post by Verg
template <class T> T* Duplicate( const T* pObj, int numObjects){	T *pNewObj = new T[numObjects];	memcpy( pNewObj, pObj, bytes );	return pNewObj;};


Where is "bytes" coming from? Mars? [smile]

[EDIT] AH... I see you fixed that down lower.

Well... this sounds like some type of CRT library mismatch to me... something built against a static library (of your own) that is out of date, that type of thing.


The game is built under Windows XP 32bit with the Multi-Threaded DLL (/MD)

if I replace the memcpy by a loop of my own, everything is just fine

for(u32 i = 0 ; i < bytes ; ++i)    pDest = pSource;



Well if everything is as you say it is... then the wrong code is being executed as a result of your call to "memcpy". Can you step into the memcpy.asm file?

Is "memcpy" being redefined somewhere?

A last resort would be to roll your own "memcpy" using the inline assembler (unless you're building on that 64-bit compiler...)
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
Quote:Original post by janta
@Driv3MeFar: Yeah there is. I'm not coding at home, I'm working on a large codebase like 1M lines of code and I cant afford to refactor everything. The team who originally designed the software made the choice not to use stl.


Well, std::vector and std::copy are not part of the STL, they're part of the c++ standard library.

If you don't want to use a vector that's fine, but I can't really see why you wouldn't use copy here:

template <typename T>T* Duplicate(T* pIn, int numObjs){    T* ret = new T[numObjs];    std::copy(pIn, pIn + (numObjs * sizeof(T)), ret);    return ret;}Disclaimer: This is untested, my pointer math is probably off.
That's interesting. Looking at std::copy's signature I saw it required some iterators as inputs, I did not think that mere pointers could be used as iterators. I'll try this, thanks.

@Verg: Well, memcpy is used at least a bazillion times throughout the project with no errors. The game runs really fine except when it randomly crashes. I don't think I mention the randomness by the way. Most of the times memcpy does its job, then once in a while, boom.

Also, I've taken a look at the assembly and everywhere memcpy is called there is a jmp at the same adress, so I think I can assume always the "same" memcpy is being called. I sould step into though, to see more of what really happens...

This topic is closed to new replies.

Advertisement