如何在任意指针类型上设置魔术指针值
How to set magic pointer values on arbitrary pointer types
我有一个应用程序,由于 nullptr 取消引用,我在其中遇到了一些罕见的分段错误。应用程序中的指针值遵循非常标准的生命周期:
- 我将它们初始化为 nullptr。
- 当信息可用于将它们设置为构造实例时,它们会在早期的某个时间点设置为一个值。
- 然后他们会习惯一段时间。
- 它们终于被释放了,之后我将它们设置为空。
当我对核心进行 post 分析时,了解指针是否具有 nullptr 值会很有帮助,因为它只是未初始化但未设置为实际实例(即,在步骤 1 之间)和上面的 2)或者因为它之前已经被释放(在上面的步骤 4 之后)。为了帮助进行此分析,我想使用魔术指针值来初始化和 post-free'ing 对象。我想到了 hexspeak 值,例如步骤 1 和步骤 4 的 0xCAFEBABE
和 0xDEADBEEF
。
我有多种类型的指针可以用于此目的。我发现对于任何给定类型,我都可以使用显式强制转换对其进行初始化。这是一个最小的例子:
#include <iostream>
using namespace std;
class A {
public:
A(int a) : _a{a} {};
int _a;
};
int
main(int argc, char* argv[])
{
A *a = reinterpret_cast<A*>(0xCAFEBABE);
cout << a->_a << endl;
return 0;
}
这就是我想要的:当我 运行 这样做时,它崩溃了,当我在调试器中打印 a
的值时,它打印 0x00000000cafebabe
.
然而,为每个指针类型指定 reinterpret_cast,每次初始化一次,每次销毁后一次,会变得乏味。有没有更有效的方法来完成这个?
更新
一些人添加了评论,建议我使用智能指针管理这些指针。我很欣赏此反馈的意图,但该建议不适用于这种情况,因为这不是管理这些对象生命周期的错误。一般来说,我的类在这个应用中的实例都是通过智能指针来管理的。在这次崩溃的特殊情况下,指针指向 OpenSSL 对象,这些对象使用 SSL_new 构造并使用 SSL_free 释放。但这不是重点:它们在创建连接时正确构造,并在连接消失时正确释放。这些实例不应存在于该时间范围之外。当我的应用程序的一部分尝试使用这些非实时实例之一进行写入时,该错误就会出现。为了帮助追踪这一点,我想知道写入是在连接建立之前还是在连接消失之后发生在对象上。这就是魔术指针值的用武之地。
您可以使用函数模板来消除单调乏味。
template <typename Object>
Object* get_pointer()
{
return reinterpret_cast<Object*>(0xCAFEBABE);
}
template <typename Object>
Object* get_pointer(Object* /*unused*/)
{
return get_pointer<Object>();
}
并将其用作:
A* a = get_pointer(a);
或
A* a = get_pointer<A>();
我有一个应用程序,由于 nullptr 取消引用,我在其中遇到了一些罕见的分段错误。应用程序中的指针值遵循非常标准的生命周期:
- 我将它们初始化为 nullptr。
- 当信息可用于将它们设置为构造实例时,它们会在早期的某个时间点设置为一个值。
- 然后他们会习惯一段时间。
- 它们终于被释放了,之后我将它们设置为空。
当我对核心进行 post 分析时,了解指针是否具有 nullptr 值会很有帮助,因为它只是未初始化但未设置为实际实例(即,在步骤 1 之间)和上面的 2)或者因为它之前已经被释放(在上面的步骤 4 之后)。为了帮助进行此分析,我想使用魔术指针值来初始化和 post-free'ing 对象。我想到了 hexspeak 值,例如步骤 1 和步骤 4 的 0xCAFEBABE
和 0xDEADBEEF
。
我有多种类型的指针可以用于此目的。我发现对于任何给定类型,我都可以使用显式强制转换对其进行初始化。这是一个最小的例子:
#include <iostream>
using namespace std;
class A {
public:
A(int a) : _a{a} {};
int _a;
};
int
main(int argc, char* argv[])
{
A *a = reinterpret_cast<A*>(0xCAFEBABE);
cout << a->_a << endl;
return 0;
}
这就是我想要的:当我 运行 这样做时,它崩溃了,当我在调试器中打印 a
的值时,它打印 0x00000000cafebabe
.
然而,为每个指针类型指定 reinterpret_cast,每次初始化一次,每次销毁后一次,会变得乏味。有没有更有效的方法来完成这个?
更新
一些人添加了评论,建议我使用智能指针管理这些指针。我很欣赏此反馈的意图,但该建议不适用于这种情况,因为这不是管理这些对象生命周期的错误。一般来说,我的类在这个应用中的实例都是通过智能指针来管理的。在这次崩溃的特殊情况下,指针指向 OpenSSL 对象,这些对象使用 SSL_new 构造并使用 SSL_free 释放。但这不是重点:它们在创建连接时正确构造,并在连接消失时正确释放。这些实例不应存在于该时间范围之外。当我的应用程序的一部分尝试使用这些非实时实例之一进行写入时,该错误就会出现。为了帮助追踪这一点,我想知道写入是在连接建立之前还是在连接消失之后发生在对象上。这就是魔术指针值的用武之地。
您可以使用函数模板来消除单调乏味。
template <typename Object>
Object* get_pointer()
{
return reinterpret_cast<Object*>(0xCAFEBABE);
}
template <typename Object>
Object* get_pointer(Object* /*unused*/)
{
return get_pointer<Object>();
}
并将其用作:
A* a = get_pointer(a);
或
A* a = get_pointer<A>();