为什么这个C代码进入循环? #包括 #包括 int p() { 字符数据[7]=“你好!\0”; uint64_t*ptr=((uint64_t)数据+0x18); printf(“%s”,数据); (*ptr)-=10; 返回0x00; } int main(int argc,字符**argv) { p(); }
您拥有的是未定义的行为为什么这个C代码进入循环? #包括 #包括 int p() { 字符数据[7]=“你好!\0”; uint64_t*ptr=((uint64_t)数据+0x18); printf(“%s”,数据); (*ptr)-=10; 返回0x00; } int main(int argc,字符**argv) { p(); },c,C,您拥有的是未定义的行为 #include <stdio.h> #include <stdint.h> int p() { char data[7]="Hello!\0"; uint64_t *ptr=((uint64_t)data + 0x18); printf("%s",data); (*ptr)-=10; return 0x00; } int main(int argc,char **argv) { p(); } 在
#include <stdio.h>
#include <stdint.h>
int p()
{
char data[7]="Hello!\0";
uint64_t *ptr=((uint64_t)data + 0x18);
printf("%s",data);
(*ptr)-=10;
return 0x00;
}
int main(int argc,char **argv)
{
p();
}
在绑定外写入数组会导致未定义的行为。这不是空终止字符串的正确方法。您可以选择以下选项之一
换成
char data[7]="Hello!\0";
你甚至可以
char data[7]="Hello!";
编辑:
通过这样做
char data[]="Hello!";
您正在使指针指向某个未分配的内存位置。稍后您将尝试写入此位置
uint64_t *ptr=((uint64_t)data + 0x18);
因此,访问绑定外的数组或写入未分配的内存会导致未定义的行为。您需要首先修复它们,如其他答案和注释中所述写入字符数据[7]=“Hello!\0”代码>可能是个问题,但我不认为这是问题的唯一来源 我的猜测是:
uint64_t*ptr=((uint64_t)数据+0x18)代码>
(*ptr)-=10代码>
通过这样做,您可能正在修改堆栈中的返回地址或执行类似操作。什么循环?你是说它永远挂着?你有两个问题,都会导致。实际上,它们都是相同的问题,但用两种不同的方式表达。问题是您在两个位置写入了数据
数组的边界之外。我猜代码是在修改堆栈以改变返回地址,从而导致无限循环(跳转到自身)。然而,程序实现这一点的方式是通过错误行为和错误使用未定义的行为,它只能在一些有限的系统上工作。我只是指出,在声明这样的字符数组时,不需要放入\0
。\0
自动放置在字符串的末尾,我通常不建议使用字符串初始化字符数组的长度(如果不是为了避免使用0终止符)。例如,char数据[6]=“你好!”代码>编译,但不0-终止。显式\0
可防止该错误。在这种情况下,省略这两个选项,显式长度和\0
更好。但是,如果出于某种原因,您坚持使用显式长度,那么显式\0
在我看来是一件好事,甚至更好,请将其留给编译器,char data[]=“Hello!”代码>@SouravGhosh是的,我接受。你能解释一下这个数组是如何越界的吗@RajatVerma字符串literal“Hello!\0”
是一个指向常量字符数组的指针,该数组包含'H'
,'e'
,'l'
,'o'
,!'代码>,'\0'
和'\0'
。将显式“\0”
添加到字符串中并不会结束字符串,它只会向字符串中添加另一个字符。@JoachimPileborg:仅当有空间容纳另一个0-终止符时。见上文。
(*ptr)-=10;