2012-03-19 58 views
10

我试图编译编译我的桌面上,但我的笔记本电脑,它编译,但给我只要运行这个错误完全正常的程序编译:堆损坏,但只有当笔记本电脑

Windows有在RR.exe中触发了一个断点。

这可能是由于堆损坏导致RR.exe或其中已加载的任何DLL文件存在bug。

这也可能是由于用户在RR.exe有焦点时按下F12。

输出窗口可能有更多诊断信息。

我注释掉线,直到我发现,使这是错误的行:

if(glfwOpenWindow(width_, height_, 0, 0, 0, 0, 32, 0, GLFW_WINDOW) != GL_TRUE) { 
    throw std::runtime_error("Unable to open GLFW window"); 
} 

奇怪的是,如果我更换width_height_与常量,例如800和600,它会停止堆损坏。另外,如果我只是使用由构造函数设置的默认值而不是传递值,它不会崩溃。

下面是完整的代码。以上几行代码都在Window构造函数中。

在window.h

#pragma once 

#include <iostream> 
#include <GL\glew.h> 
#include <GL\glfw.h> 

#pragma comment(lib, "opengl32.lib") 
#pragma comment(lib, "glu32.lib") 
#pragma comment(lib, "glew32.lib") 
#pragma comment(lib, "GLFW.lib") 

class Window { 
public: 
    Window(unsigned width = 800, unsigned height = 600); 
    ~Window(); 

    void clear(); 
    inline void display() { glfwSwapBuffers(); } 
    inline bool exit() { return !glfwGetWindowParam(GLFW_OPENED); } 

private: 
    unsigned width_, height_; 
}; 

window.cpp

#include "window.h" 

Window::Window(unsigned width, unsigned height) : width_(width), height_(height) { 
    if(glfwInit() != GL_TRUE) { 
     throw std::runtime_error("Unable to initialize GLFW"); 
    } 

    if(glfwOpenWindow(width_, height_, 0, 0, 0, 0, 32, 0, GLFW_WINDOW) != GL_TRUE) { //crash 
    //if(glfwOpenWindow(800, 600, 0, 0, 0, 0, 32, 0, GLFW_WINDOW) != GL_TRUE) { //no crash 
     throw std::runtime_error("Unable to open GLFW window"); 
    } 

    GLenum result = glewInit(); 
    if(result != GLEW_OK) { 
     std::stringstream ss; 
     ss << "Unable to initialize glew: " << glewGetErrorString(result); 
     throw std::runtime_error(ss.str()); 
    } 
} 

Window::~Window() { 
    glfwTerminate(); 
} 

void Window::clear() { 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 
} 

的main.cpp

#include "window.h" 

int main() { 
    Window wind(1024, 800); //crash 
    Window wind(800, 600); //crash 
    Window wind(); //works 

    return 0; 
} 
+3

+1用于提供一个完整的,相对短的测试情况。 – 2012-03-19 11:46:26

+1

你有你保证在两台机器上都有完全相同版本的系统/运行时DLL? – 2012-03-19 11:47:28

+0

它们是完全相同的DLL,.libs和pro因为我将它们放在保管箱中。 – Lerp 2012-03-19 11:50:17

回答

6

这个问题似乎领先GLFW:

我认为,你试图动态使用链接GLFW。注意GLFW头:

#if defined(_WIN32) && defined(GLFW_BUILD_DLL) 

/* We are building a Win32 DLL */ 
#define GLFWAPI  __declspec(dllexport) 
#define GLFWAPIENTRY __stdcall 
#define GLFWCALL  __stdcall 
#elif defined(_WIN32) && defined(GLFW_DLL) 

/* We are calling a Win32 DLL */ 
#if defined(__LCC__) 
    #define GLFWAPI  extern 
#else 
    #define GLFWAPI  __declspec(dllimport) 
#endif 
#define GLFWAPIENTRY __stdcall 
#define GLFWCALL  __stdcall 

#else 

/* We are either building/calling a static lib or we are non-win32 */ 
#define GLFWAPIENTRY 
#define GLFWAPI 
#define GLFWCALL 

#endif 

GLFW_BUILD_DLL同时建立DLL显然是设置,它定义的API函数与__stdcall调用转换。

但是当使用库时你还没有定义GLFW_DLL,所以你的代码假设调用了__cdecl转换。_cdecl__stdcall之间的区别一般是来电功能应该先清理堆栈,最后一种情况应清除被呼叫者。所以你清理了两次堆栈,这就是为什么你的堆栈损坏。

在我的程序中定义了GLFW_DLL之后,它包含glfw,它开始正常工作。还请注意,我使用了mingw,并且在定义了GLFW_DLL之后,必须链接到glfwdll.a而不是glfw.a

+0

这也适用于我。我设法通过将多线程调试DLL的运行时库更改为多线程DLL来实现它。你能解释为什么传递常量值而不是变量不会导致堆损坏?它是否以不同的方式调用函数,因为所有参数都是不变的? – Lerp 2012-03-20 13:09:44

+0

@Rarge,“多线程调试DLL到多线程DLL的运行时库”似乎与一些WinCRT的东西,而不是GLFW连接。既不设置常量值也不改变项目设置_prevents_堆损坏,但只_隐藏_它。 – Lol4t0 2012-03-20 13:25:59

1

堆损坏漏洞almomst从来没有表现出他们最初发生的地步,这是什么让他们如此痛苦的诊断。它在一个系统而不是另一个系统上工作的事实意味着未定义的行为。

我在代码的快速检查中没有看到任何明显的错误。如果你有权使用Purify for Windows,或者在Linux上编译能力,你可以使用valgrind。我相信这些工具中的任何一个都会比简单的代码检查有更高的成功变化。

0

另一种解决方案,我碰到:

通过改变运行时库(项目属性> C/C++>从多线程调试DLL(/ MDD)到多线程DLL(/ MD)堆损坏不不再发生。

我不知道为什么,虽然,也许有人有更多的知识可以可以在此提供一些线索。