如何检查指针地址的值是否为 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 *
将在典型的编译器上生成指针值 0xffffffff
或 0xffffffffffffffff
在 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 的范围之外,所以所有这些都是标准未定义的行为(或充其量是实现定义的行为)。您依赖于特定编译器的行为,但期望它们以“自然”方式处理这种情况是合理的。
我正在尝试取消引用指向 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. Then1 << sizeof(char*) * 8
is1 << 32
or1 << 64
.1
is anint
constant, which is likely 32 bits. Then1 << 32
and1 << 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 *
将在典型的编译器上生成指针值 0xffffffff
或 0xffffffffffffffff
在 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 的范围之外,所以所有这些都是标准未定义的行为(或充其量是实现定义的行为)。您依赖于特定编译器的行为,但期望它们以“自然”方式处理这种情况是合理的。