如何检查指针地址的值是否为 0xffffffffffffffff(即指向最大地址)?

How to check if pointer address has the value 0xffffffffffffffff (i.e., is pointing to the maximum address)?

我正在尝试取消引用指向 unsigned char* 的指针,但程序因段错误而崩溃,因为它的值始终为 0xffffffffffffffff。在取消引用指针之前,我想检查它指向的地址是否不同于 0xffffffffffffffff(以避免段错误)。如果不对 0xffffffffffffffff 进行硬编码检查,我该如何检查?即,

unsigned char* pointer;
...

// I would rather use something which works for x86 or x64 machine
if( pointer & 0xffffffffffffffff >= 0xffffffffffffffff - 1 ) {
    // exit
}

我正在研究,我发现了这个 https://www.qnx.com/developers/docs/6.4.1/dinkum_en/c99/stdint.html#UINTPTR_MAX,但是那个 UINTPTR_MAX 似乎是指针指向的整数的最大值,而不是指针地址的最大值。

问题一致,每次段错误,指针的值为0xffffffffffffffff。

我知道我应该修复我的应用程序,这样指针就不会设置为无效地址 0xffffffffffffffff,但是代码库非常庞大且复杂,我还不确定如何重现该问题。所以,虽然不明白这个指针是如何设置为无效地址的,但我想加个保护。

出于好奇,我怎样才能有目的地使指向 unsigned char* 的指针指向地址 0xffffffffffffffff(目标机器上的最大地址)?我的程序在某处执行此操作,但我不知道如何执行此操作,因为我仍在寻找罪魁祸首。

请勿使用,参考评论:

sizeof(char *) * 8 is likely 32 or 64. Then 1 << sizeof(char*) * 8 is 1 << 32 or 1 << 64. 1 is an int constant, which is likely 32 bits. Then 1 << 32 and 1 << 64 are not defined by the C standard; shifts with widths greater than or equal to the width of the left operand (after promotion) are not defined. And there is no need for any of this; UINTPTR_MAX is the value OP asks for (even if their approach is bad), and, if that were unavailable, (uintptr_t) -1 is also the value.

我做了这个测试程序,它似乎工作正常:https://ideone.com/bqgUrH

On if 1
On if 2
1 0xffffffffffffffff
2 0xfffffffffffffffd

它采用 char * 的大小(在 x86 上通常为 4 个字节)并乘以 8 将其转换为位 (32 bits),然后,它移动 1 << 32,并减去 1 使其成为 0xffffff...

#include <stdio.h>

int main(void) {
    unsigned char *p = (1 << sizeof(char*) * 8) - 1;
    unsigned char *p2 = (1 << sizeof(char*) * 8) - 3;

    if (  ((unsigned int)p & ((1 << sizeof(char*) * 8) - 1)) >= ((1 << sizeof(char*) * 8) - 2)  )
    {
        printf("On if 1\n");
    }

    if (!(((unsigned int)p2 & ((1 << sizeof(char*) * 8) - 1)) >= ((1 << sizeof(char*) * 8) - 2)))
    {
        printf("On if 2\n");
    }

    printf("1 %p\n", p);
    printf("2 %p\n", p2);
    return 0;
}

-1 转换为 unsigned char * 将在典型的编译器上生成指针值 0xffffffff0xffffffffffffffff 在 32 位或 64-位系统分别。

if (pointer == (unsigned char *)-1) {
    log_msg("The notorious 0xffffffff bug has surfaced!  Details follow...");
    log_msg(/* more info about the program state */);
    abort();
}

其他可能性包括 if (pointer == (unsigned char *)UINTPTR_MAX)if ((uintptr_t)pointer == UINTPTR_MAX)

UINTPTR_MAX seems to be the maximum value of the integer the pointer is pointing to

这是不对的。它是无符号整数类型 uintptr_t 的最大值,根据该系统上指针的大小,它通常是 32 位或 64 位整数。因此,您可以通过将此值转换为指针来获得所需的指针,或者将指针转换为 uintptr_t 并与 UINTPTR_MAX.

进行比较

未来读者注意事项:这仅适用于 OP 提到的特定情况:您已经将 0xffffffff 等确定为您试图追踪的某些特定错误所产生的值。通常,不可能在运行时测试给定指针是否指向有效对象;你必须设计你的程序,以便首先只使用有效的指针。

此外,任何时候你谈论一个不指向特定对象(并且不为 NULL)的指针时,你都在标准 C 的范围之外,所以所有这些都是标准未定义的行为(或充其量是实现定义的行为)。您依赖于特定编译器的行为,但期望它们以“自然”方式处理这种情况是合理的。