Повреждение кучи, но только при компиляции на ноутбуке - PullRequest
10 голосов
/ 19 марта 2012

Я пытаюсь скомпилировать программу, которая прекрасно компилируется на моем рабочем столе, но на моем ноутбуке, она компилируется, но выдает мне эту ошибку всякий раз, когда запускается:

Windows вызывает точку останова в RR.exe.

Это может быть связано с повреждением кучи, которая указывает на ошибку в RR.exe или любой из загруженных им DLL-библиотек.

Это также может быть связано спользователь нажимает клавишу F12, пока RR.exe находится в фокусе.

В окне вывода может содержаться больше диагностической информации.

Я закомментировал строки, пока не нашел строку, которая вызывает ошибку, котораяэто:

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 ]

6 голосов
/ 20 марта 2012

Кажется, проблема связана с 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 и мне пришлось связываться с glfwdll.a вместо glfw.a после определения GLFW_DLL.

1 голос
/ 19 марта 2012

Ошибки повреждения кучи почти никогда не проявляются в том месте, где они изначально возникают, что делает их настолько болезненными для диагностики.Тот факт, что он работает в одной системе, а не в другой, подразумевает неопределенное поведение.

Я не увидел каких-либо очевидных ошибок при быстрой проверке вашего кода.Если у вас есть доступ к Purify for Windows или вы можете компилировать в Linux, вы можете использовать valgrind.Я полагаю, что любой из этих инструментов будет иметь гораздо больший успех, чем простая проверка кода.

0 голосов
/ 20 марта 2012

Другое решение, с которым я столкнулся:

При изменении библиотеки времени выполнения (Свойства проекта> C / C ++> с Многопоточной отладочной DLL (/ MDd) на Многопоточную DLL (/ MD) повреждение кучи больше не происходит.

Я не знаю почему, хотя, возможно, кто-то с большими знаниями мог бы пролить свет на это.

...