鱼C论坛

 找回密码
 立即注册
查看: 874|回复: 7

[已解决]问一下拷贝字符串,问一下为什么可以正常打印而且值是一样的

[复制链接]
发表于 2022-1-29 22:44:15 | 显示全部楼层 |阅读模式
10鱼币
#include <stdio.h>
#include<string.h>

int main()
{
        char str1[]= "Original string";
        char str2[]="string";

        strcpy(str2,str1);

        printf("%s\n",str2);
        printf("%s\n",str1);

        return 0;
}
最佳答案
2022-1-29 22:44:16
摸你穷 发表于 2022-1-29 22:58
为了避免溢出,必须确保用于存放的数组长度足以容纳待拷贝的字符串(注意:长度需要包含结束符 '\0')。
...

这个代码不是所有机器上都能运行
这代码行为是未定义的,不同的机器很可能会给出不同的结果

调试环境直接报错
$ cat main.c
#include <stdio.h>
#include<string.h>

int main()
{
        char str1[]= "Original string";
        char str2[]="string";

        strcpy(str2,str1);

        printf("%s\n",str2);
        printf("%s\n",str1);

        return 0;
}
$ gcc-debug -o main main.c
$ ./main
=================================================================
==3378990==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd921cbd07 at pc 0x7f736c753c1b bp 0x7ffd921cbcd0 sp 0x7ffd921cb478
WRITE of size 16 at 0x7ffd921cbd07 thread T0
    #0 0x7f736c753c1a in __interceptor_strcpy /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:440
    #1 0x5625bd5a832c in main /tmp/main.c:9
    #2 0x7f736bbe8b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
    #3 0x5625bd5a80fd in _start (/tmp/main+0x10fd)

Address 0x7ffd921cbd07 is located in stack of thread T0 at offset 39 in frame
    #0 0x5625bd5a81d8 in main /tmp/main.c:5

  This frame has 2 object(s):
    [32, 39) 'str2' (line 7) <== Memory access at offset 39 overflows this variable
    [64, 80) 'str1' (line 6)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:440 in __interceptor_strcpy
Shadow bytes around the buggy address:
  0x100032431750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032431760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032431770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032431780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032431790: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
=>0x1000324317a0:[07]f2 f2 f2 00 00 f3 f3 00 00 00 00 00 00 00 00
  0x1000324317b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000324317c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000324317d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000324317e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000324317f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==3378990==ABORTING
$
$ clang -o main main.c
$ ./main
Original string
 string
$ gcc -o main main.c
$ ./main
Original string
l string
$

最佳答案

查看完整内容

这个代码不是所有机器上都能运行 这代码行为是未定义的,不同的机器很可能会给出不同的结果 调试环境直接报错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-1-29 22:44:16 | 显示全部楼层    本楼为最佳答案   
摸你穷 发表于 2022-1-29 22:58
为了避免溢出,必须确保用于存放的数组长度足以容纳待拷贝的字符串(注意:长度需要包含结束符 '\0')。
...

这个代码不是所有机器上都能运行
这代码行为是未定义的,不同的机器很可能会给出不同的结果

调试环境直接报错
$ cat main.c
#include <stdio.h>
#include<string.h>

int main()
{
        char str1[]= "Original string";
        char str2[]="string";

        strcpy(str2,str1);

        printf("%s\n",str2);
        printf("%s\n",str1);

        return 0;
}
$ gcc-debug -o main main.c
$ ./main
=================================================================
==3378990==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd921cbd07 at pc 0x7f736c753c1b bp 0x7ffd921cbcd0 sp 0x7ffd921cb478
WRITE of size 16 at 0x7ffd921cbd07 thread T0
    #0 0x7f736c753c1a in __interceptor_strcpy /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:440
    #1 0x5625bd5a832c in main /tmp/main.c:9
    #2 0x7f736bbe8b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
    #3 0x5625bd5a80fd in _start (/tmp/main+0x10fd)

Address 0x7ffd921cbd07 is located in stack of thread T0 at offset 39 in frame
    #0 0x5625bd5a81d8 in main /tmp/main.c:5

  This frame has 2 object(s):
    [32, 39) 'str2' (line 7) <== Memory access at offset 39 overflows this variable
    [64, 80) 'str1' (line 6)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:440 in __interceptor_strcpy
Shadow bytes around the buggy address:
  0x100032431750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032431760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032431770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032431780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032431790: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
=>0x1000324317a0:[07]f2 f2 f2 00 00 f3 f3 00 00 00 00 00 00 00 00
  0x1000324317b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000324317c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000324317d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000324317e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000324317f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==3378990==ABORTING
$
$ clang -o main main.c
$ ./main
Original string
 string
$ gcc -o main main.c
$ ./main
Original string
l string
$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-1-29 22:47:53 | 显示全部楼层
str1 拷贝给 str2,str1 的值覆盖了 str2 原有的值,所以是一样的啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-1-29 22:48:55 | 显示全部楼层
weekend2000 发表于 2022-1-29 22:47
str1 拷贝给 str2,str1 的值覆盖了 str2 原有的值,所以是一样的啊

可是两个字节不一样为什么可以正常拷贝并打印了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-1-29 22:50:12 | 显示全部楼层
这个是strcyp()函数的功能,如果有兴趣的话可以去看一看strcpy()函数的源码。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-1-29 22:58:02 | 显示全部楼层
weekend2000 发表于 2022-1-29 22:50
这个是strcyp()函数的功能,如果有兴趣的话可以去看一看strcpy()函数的源码。

为了避免溢出,必须确保用于存放的数组长度足以容纳待拷贝的字符串(注意:长度需要包含结束符 '\0')。
这是原话,可是对啊这里str1(16个字节)拷贝到str2(7个字节)明显是装不下啊,最重要的是最后打印str1和str2都是Original string
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-2-1 08:12:37 | 显示全部楼层
人造人 发表于 2022-1-29 22:44
这个代码不是所有机器上都能运行
这代码行为是未定义的,不同的机器很可能会给出不同的结果

是因为strcpy没有边界检查,所以不同规格编译器运行结果也不同吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-2-1 13:37:40 | 显示全部楼层
weekend2000 发表于 2022-2-1 08:12
是因为strcpy没有边界检查,所以不同规格编译器运行结果也不同吗

也可以这么理解
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-7-6 13:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表