2016-04-07 14 views
0

Ich versuche, SDL_ttf in ein Partikelgenerator-Programm zu integrieren, das ich vor kurzem geschrieben habe, aber ich bekomme immer einen Laufzeitfehler: Access violation reading location 0x00000044.. Dies geschieht, wenn ich versuche, eine Textoberfläche auf dem Spielbildschirm zu blitten. Ich habe meinen Code mehrere Male durchsucht und hatte ähnliche Probleme in der Vergangenheit, aber ich kann das Problem nicht herausfinden. Was ist das wahrscheinlichste Problem?Warum erhalte ich einen Zugriffsverletzungsfehler, wenn ich Text mit SDL2_ttf blitze?

Der Fehler tritt 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); 
} 
+0

Nach dem Erstellen von 'text' mit' TTF_RenderText_Solid' sollten Sie überprüfen, ob 'text' erfolgreich erstellt wurde, indem Sie' if (text) ... 'ausführen. 'TTF_RenderText_Solid' gibt' null' zurück, wenn die Erstellung fehlschlägt, und das würde die Zugriffsverletzung erklären: versuchen, von Null zu lesen – Chara

+0

@Chara Ich habe es versucht; Ich habe die Gültigkeit von 'text' überall dort überprüft, wo sein Zustand verändert wurde, sowie vor Funktionsaufrufen zu' SDL_BlitSurface'. Die Ausnahme wird immer noch vom selben Aufruf ausgelöst. Weißt du etwas anderes, das das Problem sein könnte? – CornOnTheMacabre

Antwort

0

Führen Sie die Anwendung im Debugger und brechen auf die Ausnahme. Überprüfen Sie den Aufrufstapel. Wenn Sie Glück haben, wird es an dem Punkt in Ihrem Code gefangen, an dem die Ausnahme aufgetreten ist. Wenn sich die Ausnahme nicht in Ihrem Code-Modul im Trap befindet, klicken Sie auf den Call-Stack (unten in der Liste), bis Sie den Teil Ihres Codes erreichen, in dem Sie die Argumente des Aufrufers überprüfen können wo es an diesem Punkt schief gelaufen ist. 0x44 ist verdächtig wie ASCII '$', haben Sie ein $ in Ihrem txt?

+0

yeah, ich habe mir den Call-Stack angeschaut und gefunden, wo die Exception geworfen wurde; Es war der Aufruf von SDL_BlitSurface() in Text :: DrawText() (Ich habe den Aufruf im obigen Code-Snippet markiert). Und nein, der einzige Text, den ich zu erstellen versucht habe, sind Zahlen, die den 8-Bit-Farbwert eines Bar-Objekts darstellen. – CornOnTheMacabre