鱼C论坛

 找回密码
 立即注册
查看: 1142|回复: 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')。
...

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

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

  4. int main()
  5. {
  6.         char str1[]= "Original string";
  7.         char str2[]="string";

  8.         strcpy(str2,str1);

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

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

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

  24.   This frame has 2 object(s):
  25.     [32, 39) 'str2' (line 7) <== Memory access at offset 39 overflows this variable
  26.     [64, 80) 'str1' (line 6)
  27. HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
  28.       (longjmp and C++ exceptions *are* supported)
  29. SUMMARY: AddressSanitizer: stack-buffer-overflow /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:440 in __interceptor_strcpy
  30. Shadow bytes around the buggy address:
  31.   0x100032431750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  32.   0x100032431760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  33.   0x100032431770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  34.   0x100032431780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  35.   0x100032431790: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
  36. =>0x1000324317a0:[07]f2 f2 f2 00 00 f3 f3 00 00 00 00 00 00 00 00
  37.   0x1000324317b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  38.   0x1000324317c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  39.   0x1000324317d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  40.   0x1000324317e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  41.   0x1000324317f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  42. Shadow byte legend (one shadow byte represents 8 application bytes):
  43.   Addressable:           00
  44.   Partially addressable: 01 02 03 04 05 06 07
  45.   Heap left redzone:       fa
  46.   Freed heap region:       fd
  47.   Stack left redzone:      f1
  48.   Stack mid redzone:       f2
  49.   Stack right redzone:     f3
  50.   Stack after return:      f5
  51.   Stack use after scope:   f8
  52.   Global redzone:          f9
  53.   Global init order:       f6
  54.   Poisoned by user:        f7
  55.   Container overflow:      fc
  56.   Array cookie:            ac
  57.   Intra object redzone:    bb
  58.   ASan internal:           fe
  59.   Left alloca redzone:     ca
  60.   Right alloca redzone:    cb
  61.   Shadow gap:              cc
  62. ==3378990==ABORTING
  63. $
复制代码

  1. $ clang -o main main.c
  2. $ ./main
  3. Original string
  4. string
  5. $ gcc -o main main.c
  6. $ ./main
  7. Original string
  8. l string
  9. $
复制代码

最佳答案

查看完整内容

这个代码不是所有机器上都能运行 这代码行为是未定义的,不同的机器很可能会给出不同的结果 调试环境直接报错
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

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

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

  4. int main()
  5. {
  6.         char str1[]= "Original string";
  7.         char str2[]="string";

  8.         strcpy(str2,str1);

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

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

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

  24.   This frame has 2 object(s):
  25.     [32, 39) 'str2' (line 7) <== Memory access at offset 39 overflows this variable
  26.     [64, 80) 'str1' (line 6)
  27. HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
  28.       (longjmp and C++ exceptions *are* supported)
  29. SUMMARY: AddressSanitizer: stack-buffer-overflow /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:440 in __interceptor_strcpy
  30. Shadow bytes around the buggy address:
  31.   0x100032431750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  32.   0x100032431760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  33.   0x100032431770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  34.   0x100032431780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  35.   0x100032431790: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
  36. =>0x1000324317a0:[07]f2 f2 f2 00 00 f3 f3 00 00 00 00 00 00 00 00
  37.   0x1000324317b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  38.   0x1000324317c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  39.   0x1000324317d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  40.   0x1000324317e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  41.   0x1000324317f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  42. Shadow byte legend (one shadow byte represents 8 application bytes):
  43.   Addressable:           00
  44.   Partially addressable: 01 02 03 04 05 06 07
  45.   Heap left redzone:       fa
  46.   Freed heap region:       fd
  47.   Stack left redzone:      f1
  48.   Stack mid redzone:       f2
  49.   Stack right redzone:     f3
  50.   Stack after return:      f5
  51.   Stack use after scope:   f8
  52.   Global redzone:          f9
  53.   Global init order:       f6
  54.   Poisoned by user:        f7
  55.   Container overflow:      fc
  56.   Array cookie:            ac
  57.   Intra object redzone:    bb
  58.   ASan internal:           fe
  59.   Left alloca redzone:     ca
  60.   Right alloca redzone:    cb
  61.   Shadow gap:              cc
  62. ==3378990==ABORTING
  63. $
复制代码

  1. $ clang -o main main.c
  2. $ ./main
  3. Original string
  4. string
  5. $ gcc -o main main.c
  6. $ ./main
  7. Original string
  8. l string
  9. $
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-1-29 22:47:53 | 显示全部楼层
str1 拷贝给 str2,str1 的值覆盖了 str2 原有的值,所以是一样的啊
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

可是两个字节不一样为什么可以正常拷贝并打印了
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-1-29 22:50:12 | 显示全部楼层
这个是strcyp()函数的功能,如果有兴趣的话可以去看一看strcpy()函数的源码。
小甲鱼最新课程 -> https://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
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

是因为strcpy没有边界检查,所以不同规格编译器运行结果也不同吗
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

也可以这么理解
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-24 22:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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