c-如何识别无效的内存地址



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

通常情况下,您不能。一个无效的地址看起来和一个有效的地址差不多。唯一可识别的无效地址是NULL

因此,在使用指针之前,请确保(这样编写代码)指针是有效的或NULL始终。这是没有办法的。

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

您可以使用mincore函数。请参阅此处的说明。

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

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

您可以在这里阅读更多关于使用mmap函数进行内存映射的内容

您可以在文件/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]

如果您的目标是专门防止SIGSEGV,请记住,您可以使用signal捕获segfault。您不需要在使用时等待(可能为时已晚)-您可以暂时重新定义SIGSEGV处理程序,通过一个简单的标识例程运行您想要检查的所有地址(读取目标值,将其写回),然后,如果您的处理程序从未检测到任何错误,请恢复原始处理程序,然后转到您的代码段,该代码段需要知道它接收到的所有地址都是安全的("安全")。如果没有,您可以向调用者提出或返回自己的错误。

然而,你通常无法判断地址是否真的有效,因为底层系统可能已经在你用malloc请求的实际对象周围分配了一些东西,访问这些区域可能不会导致程序崩溃——就读取内存的行为而言,这些地址也是有效的,即使它们不表示C对象。但是,如果您所需要做的只是验证读取外部提供的缓冲区不会导致代码崩溃,那么这不是您需要克服的障碍。

最新更新