C语言可以决定是否可以访问指针指向的内存?

时间:2015-12-12 15:41:19

标签: c pointers

实施例

如果我有指针,

int* p;
p = (int*)2; // just for test
*p = 3; // it will be crack, right?

通常,值2的指针的访问将是破解。但实际上裂缝并非如此简单。指针的无效值可能来自运行时错误。我想在访问之前找到一种检查指针的方法。

3 个答案:

答案 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 overflowsmemory leaksStatic 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,但大多数环境允许您测试是否可以写入指针......

for example

不幸的是,您无法知道指针是否指向您想要的。意思是你可以指向另一个有效的地址,与你的期望不同,并且无意中破坏了你自己的记忆......

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....