函数原型
void *memcpy(void *dest, const void *src, size_t n);
功能
从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
微软的实现:
void* __cdecl memcpy( void* dst, constvoid* src, size_tcount ) { void* ret = dst; #if defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) { externvoidRtlMoveMemory( void*,constvoid*, size_tcount ); RtlMoveMemory( dst, src, count ); } #else /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */ /* * copy from lower addresses to higher addresses */ while(count--) { *(char*)dst = *(char*)src; dst = (char*)dst + 1; src = (char*)src + 1; } #endif /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */ return(ret); }
看这段代码:
void *GetImg( const char *lpctstrImgPath, void *buf, int len ) { int imglen ; void *img = readimg( lpctstrImgPath, imglen ); memcpy( buf, img, len ); return buf; }
似乎没什么问题哈。
但是——如果当img的长度小于len时问题就来了。
之所以写成这样大概是因为memcpy跟strncpy的功能的确很相似。
根据上面的memcpy函数实现来看,在win2000之前的版本调用它是非常不安全的。
它并不会检查src参数是否为NULL也没检查count参数是否为0。这就意味着如果
src为空或者count为0,必然崩溃。(搞不清楚RtlMoveMemory是怎么实现的,
或许RtlMoveMemory更好用些。)
不多说,改成如下这样就OK:
void *GetImg( const char *lpctstrImgPath, void *buf, int len ) { int imglen ; void *img = readimg( lpctstrImgPath, imglen ); //判断一下readimg返回的长度和img是否为NULL if( img && imglen ) memcpy( buf, img, imglen > len ? len : imglen ); return buf; }
自己实现一下
void *memcpy( void *dest, void *src, size_t count ) { if( dest && src ); else return dest; void *ret = dest; while( count-- > 0 ) *((char*)dest)++ = *((char*)src)++; return ret; }
或者这样:
void *memcpy( void *dest, size_t dst, void *src, size_t s ) { if( dest && src );else return dest; void *ret = dest; size_t count = s > dst ? dst : s; while( count-- > 0 ) *((char*)dest)++ = *((char*)src)++; return ret; }
后记:
类似这样的问题,一般都很难调出。调试时会发现有时崩溃有时却很正常。想要避免它只有谨慎!谨慎!!再谨慎!!!