如何识别无效的内存地址?

时间:2014-09-15 06:08:57

标签: c linux memory

我想知道是否有某种方法可以在特定平台上识别无效的内存地址(x86 64位,对于我的情况)。在取消引用地址并抛出SIGILL / SIGSEGV错误之前,我需要它来捕获程序。

4 个答案:

答案 0 :(得分:5)

一般情况下,你不能。无效地址看起来与有效地址非常相似。唯一可识别的无效地址是NULL

因此,在使用它们之前,请确保(因此编写代码)指针有效或NULL。的 始终 即可。没有办法解决这个问题。

您可以使用工具来检测指针可能无效的位置(例如未初始化,已经释放等),但这不是您所要求的。

答案 1 :(得分:3)

您可以使用mincore功能。请参阅说明here

如果地址未映射到流程虚拟地址空间,mincore将返回错误。

这不是100%,因为内存可以映射到进程虚拟地址空间但未提交(没有分配物理页面)。如果不是全部,它将捕获大量垃圾指针。

您可以使用here

中的mmap功能详细了解内存映射

答案 2 :(得分:2)

您可以在文件/proc/self/maps中查看当前进程的所有内存映射。只需打开该文件并处理其内容:每行以两个以-分隔的十六进制数字开头,这些数字是进程可以访问的地址。

您的进程映射的所有内存地址都在那里,但其中一些可能没有读取,写入或执行权限;如果你需要检查它们,你还必须阅读并解析下一个字段。

该文件的示例内容:

$ cat /proc/self/maps
00400000-0040c000 r-xp 00000000 08:01 24340229                           /bin/cat
0060b000-0060c000 r--p 0000b000 08:01 24340229                           /bin/cat
0060c000-0060d000 rw-p 0000c000 08:01 24340229                           /bin/cat
0253e000-0255f000 rw-p 00000000 00:00 0                                  [heap]
[...]
7f050d97e000-7f050d97f000 rw-p 00000000 00:00 0 
7fff9509e000-7fff950bf000 rw-p 00000000 00:00 0                          [stack]
7fff951fe000-7fff95200000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

答案 3 :(得分:1)

如果明确阻止SIGSEGV是您的目标,请记住您可以使用signal捕获段错误。你不需要等待在使用时这样做(它可能太晚了) - 你可以暂时重新定义SIGSEGV处理程序,运行你要检查的所有地址通过简单的身份例程(读取目标值,将其写回),然后 - 如果您的处理程序从未检测到任何错误 - 恢复原始处理程序并转到需要知道其收到的所有地址都是安全的代码部分("安全")取消引用。如果没有,您可以向呼叫者提出或返回您自己的错误。

但是,您通常无法判断某个地址是否真正有效,因为底层系统可能已经使用malloc为您请求的实际对象分配了一些内容,并访问了这些区域可能不会导致程序崩溃 - 就读取内存的行为而言,这些地址实际上是有效的"有效的"即使他们不代表C对象也是如此。但是如果您需要做的就是例如确认读取外部提供的缓冲区不会导致代码崩溃,这不是您需要克服的障碍。