C 在系统崩溃之前,如何知道内存是否无效?
众所周知,访问无效内存会导致段故障,从而导致系统崩溃。我希望在系统崩溃之前知道内存是否无效。有趣的话题。请看这里的讨论: Microsoft为此提供了一个函数:IsBadReadPtr()C 在系统崩溃之前,如何知道内存是否无效?,c,linux,segmentation-fault,C,Linux,Segmentation Fault,众所周知,访问无效内存会导致段故障,从而导致系统崩溃。我希望在系统崩溃之前知道内存是否无效。有趣的话题。请看这里的讨论: Microsoft为此提供了一个函数:IsBadReadPtr() 我在Linux上找不到类似的东西。但是,您可以在valgrind()中运行程序来检测无效的指针引用。有趣的主题。请看这里的讨论: Microsoft为此提供了一个函数:IsBadReadPtr() 我在Linux上找不到类似的东西。但是,您可以在valgrind()中运行程序以检测无效指针引用。在现代多用户操
我在Linux上找不到类似的东西。但是,您可以在valgrind()中运行程序来检测无效的指针引用。有趣的主题。请看这里的讨论: Microsoft为此提供了一个函数:IsBadReadPtr()
我在Linux上找不到类似的东西。但是,您可以在valgrind()中运行程序以检测无效指针引用。在现代多用户操作系统上,无效内存访问不会使系统崩溃-它只会使进行无效访问的程序崩溃。在现代多用户操作系统上,无效的内存访问不会使系统崩溃-它只会使进行无效访问的程序崩溃。简单的回答是,没有可移植的、可靠的方法来实现这一点 这是100%正确的,也是应该的。你要问的是“我如何让我的程序检测到我的程序中有一个bug?”-唯一可以得到无效指针的方法是如果你有bug(或者仅仅是写得很糟糕的代码)
使用valgrind或类似工具来分析代码并修复导致内存访问不良的任何错误是最好的解决方案。简单的回答是,没有可移植的、可靠的方法来实现这一点 这是100%正确的,也是应该的。你要问的是“我如何让我的程序检测到我的程序中有一个bug?”-唯一可以得到无效指针的方法是如果你有bug(或者仅仅是写得很糟糕的代码)
使用valgrind或类似工具来分析代码并修复导致内存访问不良的任何错误是最好的解决方案。这是特定于Linux的,但实现起来简单可靠 打开
/proc/self/maps
。它是一个文本伪文件,列出当前进程的所有内存映射。如中所述;请参阅/proc/[pid]/maps
部分。这些线条看起来有点像
7fb5cb179000-7fb5cb32e000 r-xp 00000000 fc:00 14651 /lib/x86_64-linux-gnu/libc-2.15.so
但是,您只需要解析从十六进制到破折号-
的起始地址,从十六进制到空格
的结束地址(不包括在内;它是地图外的第一个地址),以及从一些模式字母到下一个空格
模式字母r
表示映射可读、w
可写、x
可执行、s
共享和p
私有。(未来可能会有其他字母,因此最好忽略所有字母,除了这些字母和空格
)
因为long
是C中最大的标准整数类型,所以应该使用unsigned long
作为地址(包括解析地址时)。您还可以使用(无符号长)指针
将任何指针转换为地址。使用int
无法在大多数64位Linux体系结构上工作,因为它往往是32位的,因此无法表示所有指针
如果指针地址在所有这些映射之外,那么它肯定是无效的:取消对指针的引用将导致分段错误
如果指针位于上述映射之一内,映射的模式将描述哪些操作有效,以及它是什么类型的映射。例如,如果您知道指针旨在指向数据,那么您就知道目标映射不应该是可执行的
在多线程程序中,您需要尝试一次性将整个文件读入内存,以便看到内存映射的一致快照,然后使用字符串操作解析数据。如果发现没有读取完整文件,只需重新读取该文件即可。您应该使用
unistd.h
中的低级I/O(而不是使用stdio.h
或mman.h
中的函数)来执行此操作,以避免任何缓存和抽象。事实上,我也建议单线程应用程序使用此过程;这是一种健壮的方法。这是特定于Linux的,但实现起来简单可靠
打开/proc/self/maps
。它是一个文本伪文件,列出当前进程的所有内存映射。如中所述;请参阅/proc/[pid]/maps
部分。这些线条看起来有点像
7fb5cb179000-7fb5cb32e000 r-xp 00000000 fc:00 14651 /lib/x86_64-linux-gnu/libc-2.15.so
但是,您只需要解析从十六进制到破折号-
的起始地址,从十六进制到空格
的结束地址(不包括在内;它是地图外的第一个地址),以及从一些模式字母到下一个空格
模式字母r
表示映射可读、w
可写、x
可执行、s
共享和p
私有。(未来可能会有其他字母,因此最好忽略所有字母,除了这些字母和空格
)
因为long
是C中最大的标准整数类型,所以应该使用unsigned long
作为地址(包括解析地址时)。您还可以使用(无符号长)指针
将任何指针转换为地址。使用int
无法在大多数64位Linux体系结构上工作,因为它往往是32位的,因此无法表示所有指针
如果指针地址在所有这些映射之外,那么它肯定是无效的:取消对指针的引用将导致分段错误
如果指针位于上述映射之一内,映射的模式将描述哪些操作有效,以及它是什么类型的映射。例如,如果您知道指针旨在指向数据,那么您就知道目标映射不应该是可执行的
在多线程程序中,您可以