0

众所周知,对无效内存的访问会导致段错误,从而导致系统崩溃。我希望在系统崩溃之前知道内存是否无效。

4

4 回答 4

2

这是特定于 Linux 的,但实现起来简单可靠。

打开/proc/self/maps. 它是一个文本伪文件,列出了当前进程的所有内存映射。它在man 5 proc中有描述;见/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地址(包括解析它们时)。您还可以使用 将任何指针转换为地址(unsigned long)pointer。使用intjust 不适用于大多数 64 位 Linux 架构,因为它往往是 32 位的,因此无法表示所有指针。

如果指针地址在所有这些映射之外,它肯定是无效的:取消引用指针会给你一个分段错误。

如果指针在上述映射之一内,映射的模式描述了哪些操作是有效的,以及它是什么类型的映射。例如,如果您知道指针旨在指向数据,那么您就知道目标映射不应该是可执行的。

在多线程程序中,您会想尝试一次将整个文件读入内存,这样您就会看到内存映射的一致快照,然后使用字符串操作解析数据。如果您发现您没有阅读完整的文件,只需重新阅读该文件。您应该使用 from 的低级 I/O unistd.h(而不是使用stdio.hor的函数mman.h)来执行此操作,以避免任何缓存和抽象。事实上,我也建议将此过程用于单线程应用程序;这是一种稳健的方法。

于 2012-10-18T06:01:12.240 回答
1

简短的回答是没有可移植、可靠的方法来做到这一点。

这是 100% 正确的,而且应该如此。您要问的是“我怎样才能让我的程序检测到我的程序中有错误?” - 获得无效指针的唯一方法是如果你有一个错误(或者只是简单的写得很糟糕的代码)。

使用 valgrind 或类似工具来分析代码并修复任何导致错误内存访问的错误的想法是最好的解决方案。

于 2012-10-18T04:15:51.490 回答
0

有趣的话题。请看这里的讨论:http ://www.cplusplus.com/forum/beginner/49550/

微软为此提供了一个函数:IsBadReadPtr ( http://msdn.microsoft.com/en-us/library/aa366781(VS.85).aspx )

对于 Linux,我找不到类似的东西。但是,您可以在 valgrind ( http://valgrind.org/ ) 中运行程序来检测无效的指针引用。

于 2012-10-18T03:09:29.733 回答
0

在现代多用户操作系统上,无效的内存访问不会使系统崩溃——它只会使您的程序崩溃,使您的访问无效。

于 2012-10-18T03:37:15.687 回答