使用instance-member方法作为函数指针时堆损坏?

时间:2014-03-11 22:11:31

标签: c++ visual-c++

问题:传递实例成员函数时是否需要采取特殊预防措施?

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

  1. 通过函数指针不断调用成员函数(数十万次)。
  2. 该进程最终崩溃,但堆栈跟踪有些不一致。唯一的共同点似乎是new / malloc失败了,即使有足够的进程内存可用。
  3. 据我所知,实例(下例中的CClass)仍然存在。
  4. 成员函数可以有一个空体;只是试图调用该方法 通过函数指针足以破坏堆(假设它的堆损坏)。
  5. 单线程,单进程。
  6. 这是XP上的visual studio 6.0。
  7. 注意:为了解决这个问题,我让CFunctor成为CClass的朋友并让它访问CClass成员;但我想知道我的原始方法是否从一开始就存在缺陷。

    简化示例:

    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 );
        }   
    }
    

2 个答案:

答案 0 :(得分:0)

我在这里看到两个CFunctor构造函数,其中一个应该是析构函数,但它前面没有波形符...

方法CFunctor::calculate被声明为虚拟,所以你可能使用一些派生类MyFunctor,而不是CFunctor本身?可能您忘记将MyFunctor构造函数中的适当数据传递给基类CFunctor构造函数。默认构造函数将基本成员初始化为NULL,这会导致calculate(args)中的内存访问错误。

答案 1 :(得分:0)

您提到了内存问题,在示例中,您提供的类可以在不破坏内存的情况下分配内存。

您似乎在析构函数中为您的成员分配NULL。这没用。在c ++中,使用new释放delete的内容,或者尽可能使用智能指针。分配给NULL只会更改指针,但不会释放任何内容。

另外,如果您有非默认的复制构造函数/析构函数/复制赋值,则很可能need all three