【发布时间】:2019-08-07 14:19:04
【问题描述】:
我有以下代码:
#include<stdio.h>
#include <string.h>
int main(void) {
char *src = "This is my string.";
char *dest, *ret;
//char dest[64], *ret;
ret = strncpy(dest, src, 5);
size_t s = strlen(ret);
printf("src: %s\n", src);
printf("dst: %s|\n", dest);
printf("ret: %s|\n", ret);
printf("len: %d\n", s);
//for (int i = 0; i < 5; i++) {
// printf("i: %d\n", i);
//}
return 0;
}
for 循环已禁用
$ gcc -g -o test test.c; ./test
src: This is my string.
dst: This |
ret: This |
len: 5
for 循环启用
$ gcc -g -o test test.c; ./test
Segmentation fault (core dumped)
我想知道为什么只有在启用for 循环时才会失败。
这只是一个未定义的行为,因为我在 dest 参数中使用了一个悬空指针,还是对此有其他解释?
通过查看gdb 会话,它在尝试将值从ecx 分配到rdi 寄存器时崩溃了?
(gdb) bt
#0 0x00007ffff7f4a1a7 in __strncpy_avx2 () from /lib64/libc.so.6
#1 0x000000000040116e in main () at stack.c:8
(gdb) x/i 0x00007ffff7f4a1a7
=> 0x7ffff7f4a1a7 <__strncpy_avx2+1591>: mov DWORD PTR [rdi],ecx
(gdb) x/i $rdi
0x401060 <_start>: endbr64
(gdb) p $rdi
$7 = 4198496
(gdb) p $ecx
$8 = 1936287828
【问题讨论】:
-
指针 char *dest 未初始化。
-
这是未定义的行为。您正在使用未初始化的指针。
strncpy取消引用此指针,该指针可能具有任何值,并尝试写入该内存。您需要有一个由有效内存组成的目标缓冲区,并传递一个指向该缓冲区的指针。 -
@HTF 这是未定义的行为。任何事情都可能发生,或者没有什么不好的事情发生。你无法预测。您正在做的事情可能会弄乱其他任意变量。未定义行为的影响范围超出了您执行该行为的位置。一旦你的程序中有任何东西,整个程序的行为是不确定的,你无法再预测会发生什么。
-
另请注意,strncpy 并不是真正的字符串函数,因为它不一定会在目标中生成以 NUL 结尾的 C 字符串。一个好的经验法则是“永远不要使用 strncpy”,因为 99% 的用例都不能满足您的要求。如果你有那 1%,你就会知道。
-
知道为什么只有在启用 for 循环时才会发生这种情况吗? 这基本上就像在问:“昨天,我开车闯红灯,但什么也没发生。今天我打开了收音机,当我开车闯红灯时,一辆卡车撞上了我。知道为什么只有当我打开收音机时才会发生这种情况吗?”