我遇到的问题是由于在简单的FreeGLUT C ++应用程序中可能误用线程而产生的。
由于退出glutMainLoop()
不能优雅地完成,我依靠glutLeaveMainLoop()
来完成一些工作,但是这个并没有真正将控制权交还给程序的main
功能。我有一个全局指针,它将在GL调用之前在main
函数中设置为在堆上创建的对象实例。在不使用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实例化,我仍然会得到特殊的行为。
答案 0 :(得分: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>
才能获得定义。