Jump to content
  • Advertisement
Sign in to follow this  
janta

memcpy not copying

This topic is 4058 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
Advertisement
Have you stepped through with a debugger?

Looked at the generated assembly?

I wouldn't hazard a guess without both of these things

Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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);
}

Share this post


Link to post
Share on other sites
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.



Share this post


Link to post
Share on other sites
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...)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!