实施例
如果我有指针,
int* p;
p = (int*)2; // just for test
*p = 3; // it will be crack, right?
通常,值2的指针的访问将是破解。但实际上裂缝并非如此简单。指针的无效值可能来自运行时错误。我想在访问之前找到一种检查指针的方法。
答案 0 :(得分:6)
在标准C99中,此{(int*)2
语句中的*p =3;
取消引用)为undefined behavior(UB)。阅读C.Lattner's blog。你应该be very scared of UB。这就是为什么用C编程很难(其他编程语言如Ocaml,Common Lisp的UB要少得多)。
C程序可能有未定义的行为,但可能并不总是崩溃。
实际上,在用C编码时,要注意指针。明确地初始化所有这些(通常是NULL
)。指针算法要非常小心。避免使用buffer overflows和memory leaks。 Static source code analysis可能会有所帮助(例如Frama-C}但有限(请参阅halting problem& Rice's theorem)。您可以经常使用flexible array members并在运行时检查指针和索引。
在一些嵌入式独立C实现(例如,Arduino类设备的编码)中,某些地址可能具有特定含义(例如,某些物理IO设备),因此UB可能非常可怕
(我在下面关注Linux)
在某些实现和某些操作系统上,您可以测试地址是否有效。例如,在Linux上,您可以解析/proc/self/maps
以计算某个给定地址是否有效(有关/proc/
的更多信息,请参阅proc(5))。
(因此,您可以在Linux上编写一些函数bool isreadableaddress(void*)
来解析/proc/self/maps
并告诉您virtual address space process中的地址是否可读因为需要多个system calls)
你应该使用valgrind并编译所有警告&调试选项(gcc -Wall -Wextra -g
)并使用调试器(gdb
)以及更多debugging compiler options,例如-fsanitize=address
您可能处理SIGSEGV
信号,但it 非常棘手且非常不便携(特定于操作系统,处理器和ABI) 。除非你是一个古茹,否则你甚至不应该尝试。
答案 1 :(得分:3)
是的,"它会破解"。
你的程序无法知道一个任意初始化的指针是否实际上是" work"在运行时。首先,在运行代码之前编译代码,可能在完全不同的计算机上编译代码。编译器无法预测未来。
该语言通过说任何指针未明确指向您在程序中创建的对象或数组,只要您想要计划有明确的行为。
基本上,唯一的方法是不要这样做。
答案 2 :(得分:0)
实际上有可能......有点......
不是使用普通的C,但大多数环境允许您测试是否可以写入指针......
不幸的是,您无法知道指针是否指向您想要的。意思是你可以指向另一个有效的地址,与你的期望不同,并且无意中破坏了你自己的记忆......
char a[2];
int b; // assuming they are stored on the stack sequentially and aligned one right after the other...
char *ptr = (char*)a;
ptr += 3;
*ptr = 'b' // valid pointer, but probably an error....