C++ 将实例成员方法用作函数指针时堆损坏?

C++ 将实例成员方法用作函数指针时堆损坏?,c++,visual-c++,C++,Visual C++,问题:在传递实例成员函数时,是否需要特别的预防措施 场景:当我传递并调用实例成员函数时,偶发崩溃 通过函数指针不断调用成员函数(数十万次) 进程最终崩溃,但堆栈跟踪有点不一致。唯一的共同点似乎是new/malloc失败,尽管有大量可用的进程内存 就我所知,该实例(下面示例中的类)仍然是活动的 成员函数可以有一个空的主体;只是尝试调用该方法 通过函数指针足以损坏堆(假设是堆损坏) 单线程,单进程 这是XP上的visual studio 6.0 注意:为了回避这个问题,我让CFunctor成为类的朋

问题:在传递实例成员函数时,是否需要特别的预防措施

场景:当我传递并调用实例成员函数时,偶发崩溃

  • 通过函数指针不断调用成员函数(数十万次)
  • 进程最终崩溃,但堆栈跟踪有点不一致。唯一的共同点似乎是new/malloc失败,尽管有大量可用的进程内存
  • 就我所知,该实例(下面示例中的类)仍然是活动的
  • 成员函数可以有一个空的主体;只是尝试调用该方法 通过函数指针足以损坏堆(假设是堆损坏)
  • 单线程,单进程
  • 这是XP上的visual studio 6.0
  • 注意:为了回避这个问题,我让CFunctor成为类的朋友,并允许它访问类成员;但我想知道我最初的方法是否从一开始就存在缺陷

    一个简化的例子:

    class CFunctor
    {
    private:
        typedef void (CClass::*Calculator)(args);
    
        CClass *c;
        Calculator func;
    
    public:
        CFunctor(CClass* c, Calculator func)
        {
            this->c = c;
            this->func = func;
        };
        ~CFunctor()
        {
            this->c = NULL;
            this->func = NULL;
        }
    
        virtual void calculate(args)
        {
            (c->*func)(args);
        }
    };
    
    class CFunctorConsumer
    {
    public:
        CFunctorConsumer(CFunctor *functor)
        {
            this->functor = functor;
        }
        ~CFunctorConsumer()
        {
            this->functor = NULL;
        }
    
        virtual void DoStuff(args)
        {
           if (this->functor)
           {
               this->functor->calculate(args);
           }
        }
    
    private:
        CFunctor *functor;
    }
    
    class CClass
    {
    private:
        CFunctorConsumer* testFunctor;
    
        void CalculationMethod(args)
        {
           // This method can be empty, and still crashes
        }
    
    public:
        CClass()
        {
            this->testFunctor = new CFunctorConsumer(new CFunctor(this, this->CalculationMethod));
        }
        void Test()
        {
           this->testFunctor->DoStuff( args );
        }   
    }
    

    我在这里看到了两个
    CFunctor
    构造函数,其中一个应该是析构函数,但前面没有tilde


    方法
    CFunctor::calculate
    声明为虚拟,因此您可能使用某个派生类
    MyFunctor
    ,而不是
    CFunctor
    本身?您可能忘记了将适当的数据从
    MyFunctor
    构造函数传递给基类
    CFunctor
    构造函数。默认构造函数将基成员初始化为NULL,这会导致
    计算(args)
    中的内存访问错误您提到内存问题,并且在示例中,您为类提供了分配内存而从不销毁内存的方法

    您似乎正在为析构函数中的成员分配NULL。这是没有用的。在C++中,用<代码>删除> /COD>重新分配你的代码>新< /代码>,或者在可能的时候使用智能指针。赋值为NULL只会更改指针,但不会释放任何内容


    另外,如果您有非默认的复制构造函数/析构函数/复制赋值,则最有可能是。

    修复了该示例。默认构造函数实际上是一个析构函数。对于释放和免费析构函数代码来说,这已经足够公平了。因此,如果我正确地管理实例生命周期(即,我自己的代码中没有bug),那么传递实例成员函数并调用它本身就没有什么不安全的地方吗?我很久很久没有接触过C/C++了。你试过在调试器中运行它吗?它应该告诉你程序停止的地方。如果您不确定类对象是否存在/一致性,请添加析构函数并在其中设置陷阱(调试器的断点或一些代码来重置类对象的全局标志/计数器)。您还可以在对象的开头添加一些成员,并使用特定模式对其进行初始化,然后将其签入
    CalculationMethod
    。这并不能阻止撞车,但可以提供撞车原因的线索。。。