2

我有一个 C++ 控制台应用程序,它看起来像这样:

SomeObj* obj;

BOOL WINAPI closeHandler(DWORD cEvent)
{
   obj->Stop();
   while( obj != 0 )
   {
       Sleep(100);
   }
   return TRUE;
}

int main(int argc, char* argv[])
{
    SetConsoleCtrlHandler( (PHANDLER_ROUTINE)SignalHandler, true );
    obj = new SomeObj();
    obj->Execute();
    delete obj;
    return 0;
}

SomeObj::Execute()本质上是一个一直运行直到SomeObj::Stop()被调用的循环。当我执行 CTRL+C 时,我可以看到应用程序obj在退出之前已正确删除。但是,当我单击控制台窗口上的关闭按钮时,我发现obj它没有被正确删除。

进一步的调试表明 closeHandler 实际上被调用了,但不知何故obj并没有被删除。奇怪的是,如果我在该行上放置一个断点return 0并尝试关闭控制台窗口,我最终会遇到该断点并看到它obj已被删除。

我在这里做错了什么?有没有更好的方法来释放控制台窗口关闭事件中的东西?

4

3 回答 3

2

我猜你的 closeHandler() 例程实际上永远不会完成,因为它正在等待 obj 变为 0(大概你的意思是“NULL”或 C++11 风格的“nullptr”)。删除对象不会将指向它的指针设置为 null。老实说,我不确定为什么它有这个循环?

于 2013-06-25T20:34:51.007 回答
1

是的,有一种方法不需要您手动调用 delete 或将指针设置为 null。使用智能指针,例如std::unique_ptr. 您也不必等待对象被删除,因为一旦Execute完成并main返回,清理将被正确处理。

#include <iostream>
#include <memory>

// sample test object that oeprates as described in your question.    
struct Object
{
    Object() : running_(true) {}
    ~Object()
    {
        std::cout << "Object deleted" << std::endl;
    }
    void Stop() { running_ = false; }
    void Execute() { while(running_ == true); }

    bool running_;
};

// incredibly smart pointer!
std::unique_ptr<Object>   obj;

BOOL WINAPI closeHandler(DWORD)
{
    // We need to call stop on the object if it exists
    // use appropriate locks for multithreaded environment
    if(obj != nullptr)
    {
       obj->Stop();
       // no need to wait
    }
    return TRUE;
}

int main()
{
    SetConsoleCtrlHandler( closeHandler, true );

    // Allocate the object and execute    
    obj.reset(new Object());
    obj->Execute();
}
于 2013-06-26T02:03:46.640 回答
1

我建议您的处理程序实际上并没有删除该对象。您将 obj 指定为全局对象,但实际上并未在 closeHandler 中将其删除。也许像下面这样......

BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
{
  if (CTRL_CLOSE_EVENT == dwCtrlType)
  {
    if (NULL != obj)
    {
      delete obj;
      obj = NULL
    }
  }
}
于 2013-06-25T20:14:21.763 回答