0

我遇到的问题是由于在一个简单的 FreeGLUT C++ 应用程序中可能滥用线程而产生的。

由于退出glutMainLoop()不能优雅地完成,我依靠glutLeaveMainLoop()做一些工作,但这并没有真正将控制权交还给程序的main功能。我有一个全局指针,它将在mainGL 调用之前在函数中设置到在堆上创建的对象实例。如果不使用atexit回调,没有人会delete在这个实例上调用操作员,尽管我在调用之后放置了这样的操作glutMainLoop(现在因为它的无用而评论)。

这是我正在做的伪代码(我不会发布实际代码,因为它太长而无法过滤):

CWorld* g_world;

AtExit()
{
 delete g_world;
}
void main()
{
  atexit(AtExit);
  // create an instance of an object that creates a thread in its constructor
  // via the new operator and joins this thread in its destructor
  // calling the delete operator on that pointer to the thread instance
  CWidget thisObjectCreatesATinyThread;

  g_world = new CWorld();
  ...
  glutMainLoop();
  // delete g_world;
}

请注意,在 main 函数中,我还包含了一个小部件实例,该实例通过在其构造函数中创建的线程完成一些工作。该线程在其析构函数中加入,然后通过delete.

错误的行为:没有设置atexit回调,我得到资源泄漏,因为CWorld对象的析构函数不会被调用。如果我设置了这个回调,那么delete操作符会因为某种原因被调用两次,即使该AtExit函数只被调用一次。

在哪里寻找这种奇怪行为的根源?

即使我禁用 CWidget 实例化,我仍然会得到特殊的行为。

4

1 回答 1

1

我假设您没有使用原始的 GLUT 库(因为它很古老),而是使用 FreeGLUT,它是最广泛使用的 GLUT 实现。为了让 glutMainLoop() 返回,您将执行以下操作:

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);

在调用 glutMainLoop() 之前。如果在调用 glutLeaveMainLoop() 时没有更多活动的顶层窗口,这将导致它返回。如果您不关心仍然处于活动状态的窗口,请执行以下操作:

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);

您可能必须包含<GL/freeglut.h>而不是<GL/glut.h>才能获得定义。

于 2012-12-14T16:14:33.587 回答