请自己写出strcpy函数

char s[100]="1234";  
strcpy(s+3,s);  
printf("%s",s); 
输出结果是1231234234 
不理解这是为什么? 
------------------------------------------------ 

已知strcpy函数如下所示:

char * strcpy(char *dest, char *source) 
{  
     char *temp = dest;  
     while((*dest++ = *source++) != '\0');  
     return temp; 
}  

现在不去调用库函数,自定义一个函数,参数和内容与库函数strcpy一样,程序会朋崩溃。 

解答:

这问题必须要去逆向库函数才能说明白的...真是懒得弄了...太繁琐... 

.text:004013B3 mov     [esp+90h+var_90], eax 
 .text:004013B6 call    strcpy     ; DWORD 75A18D6E 
 .text:004013BB lea     eax, [esp+90h+var_74]     ; "123" + "1234123" 
   
 ;strcpy() in msvcrt.dll, Windows only! 
 msvcrt.dll:75A18D6E msvcrt__mbscpy: 
 msvcrt.dll:75A18D6E push    edi 
 msvcrt.dll:75A18D6F mov     edi, [esp+8] 
 msvcrt.dll:75A18D73 jmp     short loc_75A18DAC 
   
 msvcrt.dll:75A18DAC loc_75A18DAC: 
 msvcrt.dll:75A18DAC mov     ecx, [esp+0Ch]         ; &"1234" 
 msvcrt.dll:75A18DB0 test    ecx, 3 
 msvcrt.dll:75A18DB6 jnz     short loc_75A18E17     ; !(ecx & 3) 
   
 msvcrt.dll:75A18DB8 mov     edx, 7EFEFEFFh 
 msvcrt.dll:75A18DBD mov     eax, [ecx]     ; &"1234" 
 msvcrt.dll:75A18DBF add     edx, eax 
 msvcrt.dll:75A18DC1 xor     eax, 0FFFFFFFFh 
 msvcrt.dll:75A18DC4 xor     eax, edx 
 msvcrt.dll:75A18DC6 mov     edx, [ecx]     ; &"1234" 
 msvcrt.dll:75A18DC8 add     ecx, 4     ; &ecx + 1 (向后移动了一个地址) 
 msvcrt.dll:75A18DCB test    eax, 81010100h 
 ;msvcrt.dll:75A18DD0 jnz     short loc_75A18DD9 
   
 msvcrt.dll:75A18DD2 mov     [edi], edx     ; "1234" 
 msvcrt.dll:75A18DD4 add     edi, 4     ; &edi + 1 (向后移动了一个地址) 
 msvcrt.dll:75A18DD7 jmp     short loc_75A18DB8 
   
 ;back to loc_75A18DB8 
 msvcrt.dll:75A18DB8 mov     edx, 7EFEFEFFh 
 msvcrt.dll:75A18DBD mov     eax, [ecx]     ; &"234" 
 msvcrt.dll:75A18DBF add     edx, eax 
 msvcrt.dll:75A18DC1 xor     eax, 0FFFFFFFFh 
 msvcrt.dll:75A18DC4 xor     eax, edx 
 msvcrt.dll:75A18DC6 mov     edx, [ecx]     ; &"234" 
 msvcrt.dll:75A18DC8 add     ecx, 4 
 msvcrt.dll:75A18DCB test    eax, 81010100h 
 msvcrt.dll:75A18DD0 jnz     short loc_75A18DD9 
   
 msvcrt.dll:75A18DD9 loc_75A18DD9: 
 msvcrt.dll:75A18DD9 test    dl, dl 
 msvcrt.dll:75A18DDB jz      short loc_75A18E0F 
 msvcrt.dll:75A18DDD test    dh, dh 
 msvcrt.dll:75A18DDF jz      short loc_75A18DF6 
 msvcrt.dll:75A18DE1 test    edx, 0FF0000h 
 msvcrt.dll:75A18DE7 jnz     short loc_75A18DFF 
   
 msvcrt.dll:75A18DFF loc_75A18DFF: 
 msvcrt.dll:75A18DFF test    edx, 0FF000000h 
 msvcrt.dll:75A18E05 jnz     short loc_75A18DD2 
 msvcrt.dll:75A18E07 mov     [edi], edx     ; "234" 
 msvcrt.dll:75A18E09 mov     eax, [esp+8]     ; "1234234" 
 msvcrt.dll:75A18E0D pop     edi     ; return "1234234" 
 msvcrt.dll:75A18E0E retn

实在懒得解说了,精力不比当年啊...重要的步骤我都用;注释成伪C代码风格了...自己研究吧... 
  
而你自己写的那个strcpy,如@binux所说,s在累加的时候,会把结尾符'\0'覆盖掉,所以循环永远也结束不了的,会把栈直接压崩~单步跟一下就会明白是怎么回事了~ 
  
另外,必须要指出的是,strcpy按照要求是不允许dst和src有内存重叠的! 

=========================

内存区重叠了,strcpy的结果不确定。 
  
分析了下反汇编的代码,出现问题的关键原因在于,strcpy并不是逐个字符进行复制,而是一次复制4个字节。 
第一次复制4个字节,src指向字符“1”,dst指向字符“4”,复制的字符为“1234”,所以第一次复制后的结果为“1231234”;到这一步是容易理解的。 
  
之后src+4,指向新字符串的第二个字符“2”,dst+4,指向新字符串末尾,接下来就出现问题了: 
由于内存已经被改写,接下来复制了新串末尾的“234”三个字符,然后结束。 
所以最终的字符串为“1231234234”。 
  
其实这里面还有一个问题,如果字符串后面的内存中没有出现0的话,strcpy会一直复制下去,并不会结束。 
如果把代码改一下: 
     char s[100]="1234";   
     s[7] = 'B'; 
     s[11] = 'U'; 
     s[15] = 'P'; 
     s[19] = 'T'; 
     strcpy(s+3,s);   
     printf("%s",s); 
输出结果是 1231234234B34BU4BUPBUPTUPT 

====================================

由后往前移指copy~ 

char* strcpy_safe(char* dst,const char* src) 
 { 
     size_t len = strlen(src); 
     char* cp = dst; 
     if(dst == NULL) 
     { 
         return NULL; 
     } 
   
     if(dst<=src || (char*)dst >= ((char*)src + len)) 
     { 
         while(*src) 
         { 
             *dst++ = *src++; 
         } 
         *dst = '/0'; 
         return cp; 
     } 
     else
     { 
         dst = (char*)dst + len; 
         *dst-- = '/0'; 
         src = (char*)src + len - 1; 
           
         while(len--) 
         { 
             *dst-- = *src--; 
         } 
   
         return cp; 
     } 
 }

==============================

#include <stddef.h> 
 #include <string.h> 
 #include <memcopy.h> 
 #include <bp-checks.h> 
 #undef strcpy 
   
 /* Copy SRC to DEST.  */
 char * 
 strcpy (dest, src) 
      char *dest; 
      const char *src; 
 { 
   reg_char c; 
   char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src); 
   const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1; 
   size_t n; 
   do
     { 
       c = *s++; 
       s[off] = c; 
     } 
   while (c != '\0'); 
   
   n = s - src; 
   (void) CHECK_BOUNDS_HIGH (src + n); 
   (void) CHECK_BOUNDS_HIGH (dest + n); 
   return dest; 
 } 
 libc_hidden_builtin_def (strcpy)
这个应该是源码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值