This may be a total obvious error for some, but I can't seem to find out why this segmentation fault happens.
I do understand that segmentation faults occur when accessing an address that my program should not access.
First, I have this base-class called "UiObject":
class UiObject {
private:
public:
UiObject();
virtual void render(char * imageBuffer) = 0;
};
Then, I am deriving multiple other classes from the UiObject class: For example, the ProgressBar class:
class ProgressBar : public UiObject {
private:
int x,y; // Position der ProgressBar auf dem Bildschirm (oben links) (Pixeln)
int width,height; // Breite und Höhe in Pixeln
public:
int maxProgress; // Maximal zu erreichner Fortschritt
long progress; // Fortschritt aktuell
ProgressBar(); // Constructor
void render(char * framebuffer); // Rendermethode
};
Now, these objects are managed and rendered by an UiManager. The function renderDisplay() is a thread created with std::thread:
void UiManager::renderDisplays() {
printf("[RENDER] Render thread has been started\n[RENDER] (%x)\n", this);
while(!this->shouldStop) {
// Removed code that manages the timing of this function (running approximately 60FPS)
// Rendering:
for(Display d: displayArray) {
char * framebuffer = d.getFrameBuffer();
printf("Framebuffer: %x\n", framebuffer);
printf("uiArray: %x\n", uiArray);
printf("&uiArray: %x\n", &uiArray);
for(UiObject* pObject : uiArray) {
printf("[RENDER] (%x) Rendering Object...", pObject);
pObject->render(framebuffer);
}
d.renderDisplay();
}
}
}
As you can see, for every added Display I am retrieving the framebuffer. I'm opening the /dev/fbX files so i can draw directly onto the screen. This all works fine. d.getFramebuffer() returns a char * pointer so i can manipulate the pixels, which is then passed into the render(char * framebuffer) function of any UiObject.
However, this function call is creating a segfault, and I can't understand why. There are sometimes when it works and just runs until the thread should stop, and sometimes it crashes immidiately after the first render-function call.
I add the UiObjects to the UiManager using this:
ProgressBar pBar;
pBar.maxProgress = 60*15;
pBar.progress = 1;
uiArray.push_back(&pBar);
The UiManager has this as its class-definition:
class UiManager {
private:
char ttyfd; // TTY File Descriptor.
std::thread uiManagerThread;
std::chrono::system_clock::time_point timeA;
std::chrono::system_clock::time_point timeB;
std::chrono::duration<double, std::milli> work_time;
public:
std::vector<Display> displayArray;
std::vector<UiObject*> uiArray;
bool shouldStop;
bool displayFPS;
UiManager();
void stop();
void renderDisplays();
void addDisplay(Display d);
void startThread();
void stopThread();
};
Now I'm wondering why this is.
According to the cppreference https://en.cppreference.com/w/cpp/language/abstract_class and their documentation about abstract classes, I'm not allowed to have the =0; in my UiObject class. If I remove it, I will get compiler warnings during linking with the message "undefined reference to vtable for UiObject".
What have I done wrong?
I suspect that the std::vector and the for-loop are not quite working in the UiManager.
Im using g++ on debian as my compiler.
My console output:
[RENDER] Render thread has been started
[RENDER] (6ea609f0)
Framebuffer: e09f0010
uiArray: e09eed20
&uiArray: 6ea60a30
./run.sh: Zeile 21: 25018 Speicherzugriffsfehler ./a.out
It also does not even jump into the ProgressBar render routine. I also commented out the contents of the render-function, therefore i can only suspect that specific function call.