zoukankan      html  css  js  c++  java
  • VC之那些 strcpy 往事

    首先让我们看看VC6.0里面库函数   strcpy源码:

    1 char * __cdecl strcpy(char * dst, const char * src)
    2 {
    3 char * cp = dst;
    4
    5 while( *cp++ = *src++ )
    6 ; /* Copy src over dst */
    7
    8 return( dst );
    9 }

    可以看到代码简单,第一个没有考虑目的字符串与源字符串的大小比较,他就是只管拷贝,不管指针是否越界。

    那么我们先测试一小段程序:

    #include <stdio.h>

    int _tmain(int argc, _TCHAR* argv[])
    {

    char strb[]="999456789";
    char stra[]="123";

    strcpy(stra,strb);

    printf("stra=%s\nstrb=%s\n",stra,strb);

    }

    这个测试程序在VC6.0环境 运行结果是 stra=999456789     strb=56789

                          在VC9.0环境运行结果是 stra=999456789      strb=999456789   同时越界报错

    好了 我们的问题来了,为什么结果不一样,其实VC6.0内存分配策略很傻比,就是 123\0999456789  那么strcpy之后呢?

    变成 999456789\0789   因而stra变成999456789,而strb指针未变仍指向第五位,所以输出56789遇\0结束。

    VC9.0内存分配策略聪明的多,他是如何解决呢,他是在strcpy的时候分给stra和strb同样大小的内存,但是stra越界要报错

    所以strcpy之前是 123\0######   999456789\0 而后strcpy的结果是999456789\0  999456789\0 这样两个字符数组被输出出来

    但是有越界访问报错。

    上面的猜测究竟对不对呢,我们在做个实验。我们知道VC9.0里面实现strcpy类都是采用汇编实现的,那好我们也采用汇编实现吧。

    我们的目的就是为了模仿VC9.0的库函数strcpy

     1 char *StrcpyUnSafe(char* dstr,const char* sstr)
    2 {
    3 __asm
    4 {
    5 mov edi,dstr;
    6 mov esi,sstr;
    7 N:
    8 mov dl,[esi];
    9 cmp dl,'\0';
    10 jz over;
    11 mov [edi],dl;
    12 inc edi;
    13 inc esi;
    14 jmp N;
    15 over:
    16 }
    17 return dstr;
    18 }
    19
    20
    21 int _tmain(int argc, _TCHAR* argv[])
    22 {
    23
    24 char strb[]="999456789";
    25 char stra[]="123";
    26
    27
    28 StrcpyUnSafe(stra,strb);
    29 printf("stra=%s\nstrb=%s\n",stra,strb);
    30 return 0;
    31 }

    将这个程序运行,我们查看结果:

    stra=999456789烫?99456789
    strb=999456789
    请按任意键继续. . .

    可以看到stra里面存放的内容 因为我们没有添加\0结束符,所以会出现越界访问到strb的内容,对,就是strb的内容,这里可以清晰表明,9.0对内存分配策略,或者只接用指针将str+3的内容变为2 可以看到内存分配结果:

    1232烫烫烫烫999456789请按任意键继续. . ..

    所以9.0显然提高了智商,预留隔开了一些字节但是如果strb太大 仍然会覆盖strb的一些内容。

    猜想属实,再次向各位大牛问声。如果你们有9.0库函数源码请发送我邮箱

    好了 上述猜想得以验证,下面俺想吧自己实现的两个strcpy粘贴下,都是自己写的,一个是安全copy一个是非安全copy,安全copy就是只能复制目的字符串所能承载的大小字符。非安全就无所谓了 但是会报错,好了,上代码吧。

     1 #include "stdafx.h"
    2 #include <stdio.h>
    3 //#include <string>
    4
    5 char *StrcpySafe(char* dstr,const char* sstr)
    6 {
    7 __asm
    8 {
    9 mov edi,dstr;
    10 mov esi,sstr;
    11 N:
    12 mov dl,[esi];
    13 cmp dl,'\0';
    14 jz over;
    15 mov al,[edi];
    16 cmp al,'\0';
    17 jz over;
    18 mov [edi],dl;
    19 inc edi;
    20 inc esi;
    21 jmp N;
    22 over:
    23 }
    24 return dstr;
    25 }
    26
    27
    28 char *StrcpyUnSafe(char* dstr,const char* sstr)
    29 {
    30 __asm
    31 {
    32 mov edi,dstr;
    33 mov esi,sstr;
    34 N:
    35 mov dl,[esi];
    36 cmp dl,'\0';
    37 jz over;
    38 mov [edi],dl;
    39 inc edi;
    40 inc esi;
    41 jmp N;
    42 over:
    43 mov [edi],'\0'
    44 }
    45 return dstr;
    46 }
    47
    48
    49 int _tmain(int argc, _TCHAR* argv[])
    50 {
    51
    52 char strb[]="999456789";
    53 char stra[]="123";
    54 char *pstr=stra;
    55 *(pstr+3)='2';
    56 printf("%s\n",pstr);
    57 char strB[]="999456789";
    58 char strA[]="123";
    59
    60
    61
    62 StrcpySafe(strA,strB);
    63 printf("strA=%s\nstrB=%s\n",strA,strB);
    64 StrcpyUnSafe(stra,strb);
    65 printf("stra=%s\nstrb=%s\n",stra,strb);
    66 return 0;
    67 }

    初次写文章难免存在很多失误,如果我是迷糊在什么地方 请告知我。谢谢!

  • 相关阅读:
    elasticsearch常用命令
    logstash向elasticsearch写入数据,如何指定多个数据template
    rsync 实现文件同步 (重要数据通过rsyncr把数据同步到不同的两台服务器上,这样可以防止服务器的硬盘故障导致数据丢失) 客户端同步时如果要排某个目录
    rdesktop 指定服务器的分频率
    /etc/sudoers 配置
    su 和 su
    rdesktop 源码安装
    通过show variables like ‘general_log%’可以看查询日志
    密钥登陆服务器 失败
    log_output参数是指定日志的存储方式
  • 原文地址:https://www.cnblogs.com/cslave/p/2376076.html
Copyright © 2011-2022 走看看