现在的位置: 首页 > 综合 > 正文

memcpy带来的灾难

2013年08月20日 ⁄ 综合 ⁄ 共 1532字 ⁄ 字号 评论关闭

函数原型

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;
}

后记:

  类似这样的问题,一般都很难调出。调试时会发现有时崩溃有时却很正常。想要避免它只有谨慎!谨慎!!再谨慎!!!

抱歉!评论已关闭.