Anton Wolfarth
Anton Wolfarth

Reputation: 21

threading this method produces a segfault, why?

So im using GLFW and the following method works when called in my main method

void Display::run() {
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */



        /* Swap Buffers And Poll */
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
}

but when i try to run it on a separate thread i get a segfault

std::thread t1(&Display::run, this);

any ideas? ask if you want any more of the code

Edit: main.cpp

#include "src/support/Display.h"

int main() {
    Display* d;
    d->start();
    return 0;
}

Display.h

#include <GLFW/glfw3.h>
#include <exception>
#include <thread>


class Display {

private:
    GLFWwindow* window;
    std::thread* displayThread;

    void run();

public:
    Display();
    void start();
    void close();
};

/* Exceptions */
struct GLFWNotInitilizedException : public std::exception
{
    const char * what () const throw ()
    {
        return "ERR: Could Not Initialize GLFW";
    }
};

struct WindowNotCreatedException : public std::exception
{
    const char * what () const throw ()
    {
        return "ERR: Could Not Create Window";
    }
};

Display.cpp

#include "Display.h"

Display::Display() {
    //init glfw
    if (!glfwInit())
        throw GLFWNotInitilizedException();

    //create window and its context
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        throw WindowNotCreatedException();
    }

    //make windows context current
    glfwMakeContextCurrent(window);

    //run(); //this works instead of calling start() which puts run() into a thread

}

/* begins the rendering of the display window contents in seperate thread */
void Display::start() {
    std::thread t1(&Display::run, this);
    displayThread = &t1;
}

/* renders contents of display window */
void Display::run() {
    while (!glfwWindowShouldClose(window)) //seg fault is output here
    {
        /* Render here */



        /* Swap Buffers And Poll */
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
}


/* to be used when closing display window */
void Display::close() {
    glfwSetWindowShouldClose(window, true);
    displayThread->join();
    glfwDestroyWindow(window);
}

Upvotes: 1

Views: 1357

Answers (2)

dascandy
dascandy

Reputation: 7292

//make windows context current
glfwMakeContextCurrent(window);

This makes it active on the CURRENT thread. Run this on the thread where you want to render and it should work. Currently it's in the constructor.

Upvotes: 2

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

Display* d;

You haven't created an object here, just an uninitialised pointer.

d->start();

This calls a member on a nonexistent object. When it tries to access any members in the run() function it just accesses garbage because there is no object.

You probably want to create an object like this:

Display d;
d.start();

Also your start function will terminate the program because you don't join the thread before it is destroyed. You should learn the basics of C++ object lifetime before trying to use threads and pointers like this.

Stop using pointers until you understand the basics. displayThread should be an actual std::thread not just a pointer to some std::thread that goes out of scope.

Then you can just do:

void Display::start() {
    displayThread = std::thread(&Display::run, this);
}

Make sure you call displayThread.join() before it is destroyed, e.g in the Display destructor.

Upvotes: 1

Related Questions