Why Am I Getting an Access Violation Error When Blitting Text With SDL2_ttf?

0

I'm attempting to integrate SDL_ttf into a particle generator program that I wrote recently, but I keep getting a runtime error: Access violation reading location 0x00000044.. This occurs when I attempt to blit a text surface to the game screen. I've scanned through my code several times, and had similar issues in the past, but I can't figure out the issue. What's most likely the problem?

The error occurs in Text.h:

#pragma once

#include "System.h"
#include <iostream>
#include <sstream>

class Text {
public:
    Text(const char *fontaddress = "times.ttf", int size = 30, const char
       *begintext = "0", int x = 0, int y = 0, SDL_Color color = { 255, 255, 255 }) {
        font = TTF_OpenFont(fontaddress, size);

        drawpos.x = x;
        drawpos.y = y;

        textcolor = color;

        text = TTF_RenderText_Solid(font, begintext, textcolor);
        if (!text)
            std::cout << "damn" << std::endl;
    }
    ~Text() {
        if (text)
            SDL_FreeSurface(text);
        TTF_CloseFont(font);
    }

    void SetText(const char *txt);
    void SetText(int txt);
    void DrawText();
private:
    TTF_Font *font;
    SDL_Rect drawpos;
    SDL_Color textcolor;
    SDL_Surface *text;
};

inline void Text::SetText(const char *txt) {
    if (text)
        SDL_FreeSurface(text);

    text = TTF_RenderText_Solid(font, txt, textcolor);
}


inline void Text::SetText(int txt) {
    if (text)
        SDL_FreeSurface(text);

    std::stringstream s;
    s << txt;
    text = TTF_RenderText_Solid(font, s.str().c_str(), textcolor);
}

inline void Text::DrawText() {
    static SDL_Surface *const screen = System::GetInstance().GetScreen();
    SDL_BlitSurface(text, NULL, screen, &drawpos);
     // ^ This line throws the exception
}

Bar.h:

#pragma once

#include <SDL.h>
#include <iostream>
#include "System.h"
#include "Text.h"

class Bar {
public:
    Bar(const int xpos = 0, const int ypos = 0, unsigned width = 0, unsigned    height = 0, const Uint32 c = SDL_MapRGB(System::GetInstance().GetScreen()-   >format, 0, 0, 0), const char *address = "times.ttf",
        int sz = 30, const char *bgtext = "0", SDL_Color co = { 255, 255,   255 }) : max_w(width), color(c), colortext(address, sz, bgtext, xpos - 50, ypos, co) {
        bar.x = xpos;
        bar.y = ypos;
        bar.w = width;
        bar.h = height;

        modval = max_w / 255;
        if (!modval)
            modval = 1;
        if (max_w < 255) {
            std::cerr << "invalid width; below 255" << std::endl;
        }
        colorval = width / modval;
    }

    void Modify(int width_modifier);
    void Draw();
    Uint8 GetColorVal();
private:
    SDL_Rect bar;
    unsigned max_w;
    Uint32 color;
    Uint8 modval;   // number of pixels (in width) required to advance or decrement the color value by 1
    Uint8 colorval; // the color value modified when width is changed. Determined by 
           // modval. This value will be used by RGBTable class for text (on-screen value display) and particle color creation
    Text colortext;
};

//inlined methods

//modifies the width of a bar
inline void Bar::Modify(int width_modifier) {
    if (bar.w + width_modifier < 0 || bar.w + width_modifier > max_w)
        return;

        bar.w += width_modifier;
        if (bar.w % modval == 0) {
            colorval = bar.w / modval;
            colortext.SetText(colorval);
        }
}


//draws bar to system screen
inline void Bar::Draw() {
    static SDL_Surface *screen = System::GetInstance().GetScreen();
    SDL_FillRect(screen, &bar, color);
    colortext.DrawText();
}


//returns the 8bit color value represented by the width of a bar
inline Uint8 Bar::GetColorVal() {
    return colorval;
}

ColorTable.h:

#pragma once 

#include "System.h"
#include "Bar.h"
#include <array>

class ColorTable {
public:
    static bool needupdate;
    static ColorTable &GetInstance();

    void Input();
    void Draw();
    Uint32 MakeColor();
private:
    ColorTable(int top_left_x, int top_left_y, unsigned width, int height,  int sepval) { 
        static SDL_Surface *screen = System::GetInstance().GetScreen();

        bars[0] = Bar(top_left_x, top_left_y, width, height, SDL_MapRGB(screen->format, 255, 0, 0));
        bars[1] = Bar(top_left_x, top_left_y + height + sepval, width, height, SDL_MapRGB(screen->format, 0, 255, 0));
        bars[2] = Bar(top_left_x, top_left_y + (sepval *2) + (height * 2), width, height, SDL_MapRGB(screen->format, 0, 0, 255));

        activebar = bars.begin();
    }

    std::array<Bar, 3> bars;
    std::array<Bar, 3>::iterator activebar;
    const Uint8 *key = SDL_GetKeyboardState(NULL);
};

inline ColorTable &ColorTable::GetInstance() {
    static ColorTable table(750, 620, 510, 50, 10);
    return table;
}

inline void ColorTable::Draw() {
    bars[0].Draw();
    bars[1].Draw();
    bars[2].Draw();
}

inline Uint32 ColorTable::MakeColor() {
    static SDL_Surface *screen = System::GetInstance().GetScreen();

    Uint8 r = bars[0].GetColorVal();
    Uint8 g = bars[1].GetColorVal();
    Uint8 b = bars[2].GetColorVal();

    return SDL_MapRGB(screen->format, r, g, b);
}
c++
sdl
sdl-ttf
asked on Stack Overflow Apr 7, 2016 by CornOnTheMacabre • edited Apr 7, 2016 by Laurel

1 Answer

0

Run the application in the debugger and break at the exception. Inspect the call stack. If you're lucky, it will trap at the point in your own code where the exception occurred. If the exception is not in your code module at the trap, click your way up the call stack (down the list presented there) until you reach the portion of your code where you can inspect the arguments of the caller, it's usually easy to spot where it went wrong at that point. 0x44 is suspiciously like ASCII '$', do you have a $ in your txt?

answered on Stack Overflow Apr 7, 2016 by QwazyWabbit

User contributions licensed under CC BY-SA 3.0