【问题标题】:Program receiving SIGSEGV may be for pointer of 0xffffffff接收 SIGSEGV 的程序可能是针对 0xffffffff 的指针
【发布时间】:2012-05-07 04:13:04
【问题描述】:

我正在用户空间中调试一个程序,并且正在接收一个 SIGSEGV 的指针,我认为该指针的值可能是 0xffffffff

我想知道0xffffffff是否是一个有效的指针地址??

我使用了 GDB,下面是代码列表:

1414
1415        /* convert object handle */
1416        file = (PSLhandle_t*)hFile;
1417
1418        /* param check */
1419        if(file->hobject.fdesc == 0)   <----------------- it may be crashing here
1420            return INVALID_SET_FILE_POINTER;





----------------- during debugging---------------------------


1412        if((hFile == NULL) || (lpBuffer == NULL))
(gdb) s
1419        if(file->hobject.fdesc == 0)
(gdb) print file
No symbol "file" in current context.
(gdb) print hFile
$1 = (HANDLE) 0xffffffff
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
WriteFile (hFile=0xffffffff, lpBuffer=0xb7f69294, nNumberOfBytesToWrite=65516, lpNumberOfBytesWritten=0xb3933238,
    lpOverlapped=0x0) at PSLWinWrapper.c:1419
1419        if(file->hobject.fdesc == 0)

我正在使用 Linux,

[root@DellB 应用程序]# uname -a Linux DellB 2.6.23.1-42.fc8 #1 SMP 2007 i686 i686 i386 GNU/Linux

我已经检查了NULL

/* param check */
if((hFile == NULL) || (lpBuffer == NULL)) <-------- CHECKED ALREADY FOR NULL
    return INVALID_SET_FILE_POINTER;

/* convert object handle */
file = (PSLhandle_t*)hFile;

/* param check */
if(file->hobject.fdesc == 0) <-------------- CRASH HERE
    return INVALID_SET_FILE_POINTER;

我想知道0xffffffff 是否是一个有效的指针地址? 是否有任何 API 可以验证指针在用户空间中的 LINUX 上是否有效。

【问题讨论】:

  • 只是一个猜测,但您并没有尝试将 unix 文件句柄转换为 FILE 流指针,是吗?它们是根本不同的东西,你需要使用fdopen()

标签: c segmentation-fault


【解决方案1】:

我相信0xffffffffINVALID_HANDLE_VALUE,至少在 32 位系统上是这样。

许多 Windows API 函数返回 INVALID_HANDLE_VALUE 以指示发生了错误。例如,来自CreateFile 文档 (source):

返回值

如果函数成功,则返回值是指定文件、设备、命名管道或邮件槽的打开句柄。

如果函数失败,返回值为INVALID_HANDLE_VALUE。要获取更多错误信息,请致电GetLastError

一般来说,任何指针值都可以指向有效内存,包括NULL。但是许多操作系统和语言运行时为无效页面保留了一个接近 0 的空间,以便在程序员取消引用 NULL 时为他们提供有用的崩溃。此空间可以双向扩展,在这种情况下,它包括 32 位系统上的 0xffffffff。 C/C++ 系统中的任何对象都不会在NULL 有地址(所以如果NULL 有什么东西,最好不要管它)。

您的第二个问题:是的,有一种方法可以检查 Linux 上的指针是否指向有效内存(这与“有效指针”的概念略有不同)。取消引用指针并查看您的程序是否存在段错误。安装信号处理程序捕获故障,使用长跳转从信号处理程序返回。

【讨论】:

    【解决方案2】:

    NULL 不是唯一的无效指针值。
    通常,访问任何不是以正常方式之一获得的指针(例如变量的地址或malloc 的返回值)都是未定义的行为。这并不意味着访问它会崩溃,但它确实意味着它可能会崩溃。

    所以测试NULL 并不能保证指针是有效的。

    具体来说,0xffffffff 在几乎所有常见平台上都是无效的。
    即使它有效,并且指向内存中的最后一个字节,你也只能访问这一个字节,因为后面的字节在地址0,肯定是无效的。

    【讨论】:

    • 大多数架构都允许您将数据放在地址 00xffffffff。 (但是,访问以0xffffffff 开头的单词几乎肯定会出错,即使在 x86 上也是如此。这并不是说它本身会失败。)大多数操作系统还允许您将数据放在地址 0 处。所以 @987654329大多数系统上的 @ 指针不保证无效,它只是保证不等于从标准 C 函数返回的任何指针或从此类指针正确派生的任何指针。这实际上是关于操作系统和编程约定,而不是架构。
    • @DietrichEpp,我认为对于主要平台上的主要操作系统,访问NULL 崩溃。我确定 x86(_64) 上的 Windows+Linux。但是你是对的,NULL 指针不能保证无效,访问它也不能保证崩溃(我认为 C 标准中的任何内容都不能保证崩溃)。
    • 是的,它在大多数主要平台上都无效。我的观点是,从架构的角度来看,它是有效的,例如 x86/ARM/PowerPC/etc,而不是操作系统/运行时决定哪些指针是有效的。所以说“0xffffffff在几乎所有架构中都无效”是不正确的,它不同于说“0xffffffff在主要桌面/服务器平台中无效”,这是正确的。
    • 稍作修改以使其更准确。
    【解决方案3】:

    具体来说,0xffffffff 是 32 位有符号整数 -1 的无符号值。您的问题的一个可能原因是任何返回 hFile 值的函数都会出错并返回 -1。当返回类型是指针时,大多数理智的程序在出错时返回 NULL,它的整数值为 0。这种情况可能是个例外。您能显示最初分配 hFile 的位置吗?

    【讨论】:

    • (void *)-1 对于系统调用来说并不罕见,尤其是那些可以在成功时返回 NULL 的调用。 mmap 可能是最常见的示例,但 Windows API 中的所有 HANDLE-returning 函数都使用相同的约定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    相关资源
    最近更新 更多