C++ 如何在任意指针类型上设置魔术指针值

C++ 如何在任意指针类型上设置魔术指针值,c++,pointers,lifetime,C++,Pointers,Lifetime,我有一个应用程序,在这个应用程序中,由于nullptr解引用,我遇到了一些罕见的分段错误。应用程序中的指针值遵循相当标准的生命周期: 我将它们初始化为nullptr 当信息可用于将它们设置为构造实例时,它们会在早期的某个点被设置为一个值 然后他们会习惯一段时间 它们最终被释放,之后我将它们设置为null 当我对一个内核进行事后分析时,了解指针是否有一个null ptr值会很有帮助,因为它只是未初始化,但没有设置为实际实例(即,在上面的步骤1和步骤2之间),或者因为它之前已被释放(在上面的步骤4之

我有一个应用程序,在这个应用程序中,由于nullptr解引用,我遇到了一些罕见的分段错误。应用程序中的指针值遵循相当标准的生命周期:

  • 我将它们初始化为nullptr
  • 当信息可用于将它们设置为构造实例时,它们会在早期的某个点被设置为一个值
  • 然后他们会习惯一段时间
  • 它们最终被释放,之后我将它们设置为null
  • 当我对一个内核进行事后分析时,了解指针是否有一个null ptr值会很有帮助,因为它只是未初始化,但没有设置为实际实例(即,在上面的步骤1和步骤2之间),或者因为它之前已被释放(在上面的步骤4之后)。为了帮助进行这种分析,我想使用魔术指针值来初始化和释放对象。对于步骤1和步骤4,我想到了诸如
    0xCAFEBABE
    0xDEADBEEF
    等hexspeak值

    我有多种类型的指针,我想用于此。我发现对于任何给定的类型,我都可以使用显式转换来初始化它。下面是一个简单的例子:

    #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;
    }
    
    #包括
    使用名称空间std;
    甲级{
    公众:
    A(int A):_A{A}{};
    国际组织;
    };
    int
    main(int argc,char*argv[])
    {
    A*A=重新解释(0xCAFEBABE);
    
    你可以用一个函数模板来消除一点繁琐的工作吗

    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();
    
    您可以使用函数模板来消除一点繁琐

    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();
    
    如果您需要此功能,我猜您还没有将容器和智能指针提升到应有的水平,并且仍在进行手动内存管理(为什么?)…您可以创建自己的smart ish指针类型来执行此初始化,并提供
    运算符*
    运算符->
    ,但这仍然无法解决问题:指针将有一段时间未初始化,您所做的任何操作都不会改变这一点。即使在您的示例中,也有一段时间
    a
    未初始化:在为a
    分配存储之间以及分配发生时。为了重申这一点,为了检查一下,我计算了我的一个库中的行数。超过25万行代码,我不相信其中有一个
    新的
    删除
    。我如果你真的坚持使用原始指针,并且重新解释cast是乏味的,只需为它编写一个函数。你可能还想看看指针标记技术(而不是使用一些神奇的数字)。通常,如果指针用于动态分配,您可以使用少数最高有效位,甚至少数最低有效位。@SamVarshavchik,这在很大程度上取决于应用程序区域。我相信大多数库可以也应该这样编写,但不是所有库都可以。如果您需要,我猜您还没有采用容器和智能poi进入您应该拥有的级别,并且仍在进行手动内存管理(为什么?)…您可以创建自己的smart ish指针类型来执行此初始化,并提供
    运算符*
    运算符->
    ,但这仍然无法解决问题:指针将有一段时间未初始化,您所做的任何操作都不会改变这一点。即使在您的示例中,也有一段时间
    a
    未初始化:在为a
    分配存储之间以及分配发生时。为了重申这一点,为了检查一下,我计算了我的一个库中的行数。超过25万行代码,我不相信其中有一个
    新的
    删除
    。我如果你真的坚持使用原始指针,并且重新解释cast是乏味的,只需为它编写一个函数。你可能还想看看指针标记技术(而不是使用一些神奇的数字)。通常,如果指针用于动态分配,您可以使用几个最高有效位,甚至是几个最低有效位。@SamVarshavchik,这在很大程度上取决于应用程序区域。我相信大多数库都可以也应该这样写,但不是所有库都可以。难道不是
    a*a=get_pointer(a);
    读取未初始化的变量时会出现错误?不会使用该值,但如果读取未优化,这是否会在某些平台上触发硬件陷阱?@cdhowie not per:“[在]对象的生存期开始之前,但在分配对象将占用的存储之后[…]引用原始对象的任何glvalue都可以使用[…]使用glvalue的属性,这些属性不依赖于原始对象的值,但定义良好。“尽管如此,请注意:从任意intefger创建指针值是错误的。@YSC不会复制该对象以将其作为参数“取决于其值”传递即使被调用方忽略它?规范中是否有一些措辞声明忽略参数的函数意味着调用方不“使用”任何将被复制来创建参数的对象?难道不是
    a*a=get\u指针(a);
    读取未初始化的变量时会出现错误?不会使用该值,但如果读取未优化,这是否会在某些平台上触发硬件陷阱?@cdhowie not per:“[在]对象的生存期开始之前,但在分配对象将占用的存储之后[…]引用原始对象的任何glvalue都可以使用[…]使用glvalue的属性,这些属性不依赖于原始对象的值,但定义良好。“尽管如此,请注意:从任意intefger创建指针值是错误的。@YSC不会复制该对象以将其作为参数“取决于其值”传递即使被调用方忽略它,规范中是否有一些措辞声明functi
    A* a = get_pointer<A>();