Strcpy,memcpy函数的内存重叠

最近想要换工作,所以复习了下C语言的知识点,在看有些面试题跟博客时发现了些问题,我在这里总结下。

大部分对strcpy考察题目是这样的,给定char * strcpy(char * strDest,const char * strSrc);原型,然后接下来是写出他的实现。

char * my_strcpy(char * strDest,const char * strSrc)
        {
                if ((strDest==NULL)||(strSrc==NULL)) //[1]
                        throw "Invalid argument(s)"; //[2]
                char * strDestCopy=strDest;  //[3]
                while ((*strDest++=*strSrc++)!='/0'); //[4]
                return strDestCopy;
        }

然后呢是1,2,3,4哪里错了扣哪里分。其实这个不是strcpy真正的实现(被骗了好多年吧,我也是看了这位博主才知道的)。为什么说strcpy不是真正的实现呢。

测试下就知道了。如下代码:

char str[10]="abc";
my_strcpy(str+1,str);
如果这样调用的话,就会出现崩溃了。

但是如果用标准库中的strcpy,不仅没有崩溃,如果打印的话还会打印出:aabc

char str[10]="abc";
strcpy(str+1,str);
所以strcpy的真正实现方式可能是以下的方式,(仅供参考)

char *my_strcpy(char *dst,const char *src)
{
	assert(dst != NULL);
	assert(src != NULL);
	char *ret = dst;
	memcpy(dst,src,strlen(src)+1);
	return ret;
}

那么问题来了,memcpy有没有很好的处理内存覆盖问题呢,其实这个也可以编写一个简单的测试语句用来测试下,

char buf[10] = "123456789";
memcpy(buf + 2,buf,5);
printf("%s\n",buf);
如果

打印:121234589说明很好的处理了内存重叠。

打印:121212189说明内存重叠没有处理。
但是在ubuntu下打印出的是: 121234389,奇怪哦。

在Windows下VC6.0下打印的是:121234589,奇怪哦。

centos下打印的是:121214589,各种奇葩结果哦。


所以Memcpy是不考虑内存重叠的,其实好多人博客上也提到了memcpy有内存重叠的问题,我们使用的是可以用memove来代替,或者使用memcpy_s(此函数适合VS2005以上版本)。

strcpy跟memcpy都没有处理内存重叠。

附录:

//vc++ memcpy
28:           char buf1[10] = "123456789";
00401178   mov         eax,[string "123456789" (00431034)]
0040117D   mov         dword ptr [ebp-0Ch],eax
00401180   mov         ecx,dword ptr [string "123456789"+4 (00431038)]
00401186   mov         dword ptr [ebp-8],ecx
00401189   mov         dx,word ptr [string "123456789"+8 (0043103c)]
00401190   mov         word ptr [ebp-4],dx
29:        memcpy(buf1+2,buf1,5);
00401194   push        5
00401196   lea         eax,[ebp-0Ch]
00401199   push        eax
0040119A   lea         ecx,[ebp-0Ah]
0040119D   push        ecx
0040119E   call        memcpy (004084b0)
004011A3   add         esp,0Ch
//vc++  strcpy
17:       char buf[10] = "123";
004010D8   mov         eax,[string "123" (00431020)]
004010DD   mov         dword ptr [ebp-0Ch],eax
004010E0   xor         ecx,ecx
004010E2   mov         dword ptr [ebp-8],ecx
004010E5   mov         word ptr [ebp-4],cx
18:       strcpy(buf+1,buf);
004010E9   lea         edx,[ebp-0Ch]
004010EC   push        edx
004010ED   lea         eax,[ebp-0Bh]
004010F0   push        eax
004010F1   call        strcpy (00408380)
004010F6   add         esp,8

//linux memcpy        
		.cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $875770417, -16(%rbp)
        movl    $943142453, -12(%rbp)
        movw    $57, -8(%rbp)
        leaq    -16(%rbp), %rax
        leaq    -16(%rbp), %rdx
        leaq    2(%rdx), %rcx
        movl    $5, %edx
        movq    %rax, %rsi
        movq    %rcx, %rdi
        call    memcpy
        leave
//linux strcpy		
		        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movq    $3355185, -16(%rbp)
        movw    $0, -8(%rbp)
        leaq    -16(%rbp), %rax
        leaq    -16(%rbp), %rdx
        addq    $1, %rdx
        movq    %rax, %rsi
        movq    %rdx, %rdi
        call    strcpy






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值