SDL - error 0xC0000005

SDL - error 0xC0000005
0

Witajcie , mam problem , jestem początkującym samoukiem w programowaniu, obecnie czytam książkę o SDL. Staram się postępować jak autor jednakże gdzieś chyba się pomyliłem i za chiny nie mogę dojść gdzie ;/
Visual wywala mi to :
First-chance exception at 0x00386CFE in Projekt1.exe: 0xC0000005: Access violation writing location 0x00000000.

Mógłbym prosic o radę?

(Nagłówek)

Kopiuj
#include "SDL.h"
#ifndef __Game__
#define __Game__
class Game
{
public:
	Game();
	~Game();
	bool init(const char* title, int xpos, int ypos, int width, int
		height, int flags);
	void render();
	void update();
	void handleEvents();
	void clean();
	bool running() { return m_bRunning; }
private:
	SDL_Window* m_pWindow;
	SDL_Renderer* m_pRenderer;
	bool m_bRunning;
};
#endif 

(Plik źródłowy)

Kopiuj
 #include <iostream>
#include <SDL.h>
#include "Nagłówek.h"

Game * g_game = 0;
int main(int argc, char* argv[])
{

	g_game->init("Chapter 1", 100, 100, 640, 480, 0);
	while (g_game->running())
	{
		g_game->handleEvents();

		g_game->render();
	}
	g_game->clean();
	return 0;
}


bool Game::init(const char* title, int xpos, int ypos, int width,
	int height, int flags)
{
	// attempt to initialize SDL
	if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
	{
		std::cout << "SDL init success\n";
		// init the window
		m_pWindow = SDL_CreateWindow(title, xpos, ypos,width, height, flags);
		

		if (m_pWindow != 0) // window init success
		{
			std::cout << "window creation success\n";
			m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
			if (m_pRenderer != 0) // renderer init success
			{
				std::cout << "renderer creation success\n";
				SDL_SetRenderDrawColor(m_pRenderer,
					255, 255, 255, 255);
			}
			else
			{
				std::cout << "renderer init fail\n";
				return false; // renderer init fail
			}
		}
		else
		{
			std::cout << "window init fail\n";
			return false; // window init fail
		}
	}
	else
	{
		std::cout << "SDL init fail\n";
		return false; // SDL init fail
	}
	std::cout << "init success\n";
	m_bRunning = true; // everything inited successfully,start the main loop
	return true;
}
void Game::render()
{
	SDL_RenderClear(m_pRenderer); // clear the renderer tothe draw color
		SDL_RenderPresent(m_pRenderer); // draw to the screen
}
void Game::clean()
{
	std::cout << "cleaning game\n";
	SDL_DestroyWindow(m_pWindow);
	SDL_DestroyRenderer(m_pRenderer);
	SDL_Quit();
}
void Game::handleEvents()
{
	SDL_Event event;
	if (SDL_PollEvent(&event))
	{
		switch (event.type)
		{
		case SDL_QUIT:
			m_bRunning = false;
			break;
		default:
			break;
		}
	}
}
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1
Kopiuj
Game * g_game = 0;
int main(int argc, char* argv[])
{
 
    g_game->init("Chapter 1", 100, 100, 640, 480, 0);

Czego sie spodziewasz wołając metodę init() na wskaźniku bez przydzielonej pamięci? W ogóle w tym kodzie widzę masę gwiazdek a ani jednego new/malloc.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
JU
  • Rejestracja:około 22 lata
  • Ostatnio:2 miesiące
  • Postów:5042
2

Nie używaj malloc, tylko new. Generalnie, jak Shalom powiedział - nie tworzysz obiektów. W C++ obiekty można tworzyć na dwa sposoby:

Kopiuj
MyClass obj;
 

To jest sposób pierwszy. Tworzysz obiekt "automatyczny". Sama deklaracja jest utworzeniem obiektu - w taki sposób za pomocą konstruktora domyślnego. Jeśli chcesz użyć konkretnego konstruktora, to po prostu:

Kopiuj
MyClass obj(parametry);

Tak utworzony obiekt zostanie automatycznie zwolniony. Tzn. jeśli np. utworzysz obiekt w funkcji, to przy wyjściu z funkcji on automatycznie zostanie zniszczony.

Drugi sposób utworzenia obiektu, to utworzenie go przez wskaźnik:

Kopiuj
MyClass * obj;

tutaj tylko DEKLARUJESZ, że obj jest wskaźnikiem na obiekt klasy MyClass. Nie jest obiektem, tylko wskaźnikiem. Aby taki wskaźnik wskazywał na obiekt musisz go albo utworzyć, albo przypisać do już istniejącego. Tworzysz przez new:

Kopiuj
MyClass * obj = new MyClass(); //lub new MyClass(parametry), jeśli chcesz użyć innego konstruktora

Tak stworzony obiekt MUSISZ samodzielnie zwolnić, gdy już go nie będziesz potrzebował. To, co stworzyłeś operatorem new, niszczysz operatorem delete:

Kopiuj
 
delete obj;

Teraz różnica w wywoływaniu metod. Jeśli obiekt jest utworzony automatycznie, wtedy do jego wnętrza wchodzisz kropką:

Kopiuj
 
MyClass obj;
obj.init();

Jeśli masz wskaźnik do obiektu, to wtedy do jego wnętrza wchodzisz strzałką:

Kopiuj
 
MyClass * obj;
obj = new MyClass();

obj -> init();
delete obj;

Pewnie dałoby się też kropką w podobny sposób (sam się dopiero uczę C++ i nie testowałem tego, ale na logikę powinno zadziałać):

Kopiuj
 
MyClass * obj = new MyClass();

(*obj).init();

delete obj;

Nawet, jeśli to działa, to zapis jest bez sensu i zaciemnia kod.

Jest też pośredni sposób tworzenia obiektów. Tzn. łączy jakby te dwa. Na pewno ma wpływ na szybkość, ale raczej niezauważalny przy zwykłych aplikacjach. Konkretnie chodzi o używanie...nie wiem dokładnie jak to się nazywa... "automatyczny wskaźnik" ?

Np:

Kopiuj
 
auto_ptr <MyClass> obj = new MyClass();

obj jest niejako wskaźnikiem na obiekt klasy MyClass, ale nie musisz go zwalniać, ponieważ to jest automatyczny wskaźnik i w odpowiednim momencie POWINIEN zwolnić się sam. Są być może lepsze odpowiedniki w bibliotece boost, np: scoped_ptr lub shared_ptr. Każde z nich ma swoje zastosowanie. Generalnie użycie takiego mechanizmu z założenia powinno wyeliminować możliwość wystąpienia memory leaków. Czy tak jest w rzeczywistości? Nie wiem, bo z C++ mam zbyt małe doświadczenie. Natomiast na pewno ogranicza memory leaki.

edytowany 2x, ostatnio: Juhas
kq
Używanie new i delete w nowym kodzie to tak jak pierdzenie w teatrze. Czasem inaczej się nie da, ale jeśli tylko jest taka możliwość to unikaj takich rozwiązań. RAII to jedna z najlepszych stron C++ i grzechem jest tego nie wykorzystywać. Pamięć nie jest jedynym zasobem kontrolowanym przez obiekty i bywają sytuacje, gdzie jest najmniej istotna (np. w porównaniu do muteksów, otwartych plików lub socketów).
robcio
gwoli ścisłości "to przy wyjściu z funkcji on automatycznie zostanie zniszczony. " tak naprawdę nic nie zostaje niszczone. Można nawet sobie zapisać adres obiektu lokalnego w funkcji zwrócić go i jest duża szansa, że ów obiekt pod tym adresem będzie istnieć po wyjściu z tejże funkcji dopóki nie zostanie zniszczony przez ramkę stosu następnej funkcji. Jednak jest to zachowanie niezdefiniowane i nie należy tak robić.
JU
Ale założyć można, że taki obiekt będzie zniszczony po wyjściu z funkcji? (bo dla programisty tak naprawdę nie jest ważne, czy zaraz po wyjściu z funkcji, czy niedługo potem, ważne żeby tego nie używać poza funkcją)
kq
Z punktu widzenia języka jest niszczony. Jakiekolwiek dywagacje na temat tego, co może w tym zakresie robić implementacja nie mają sensu - Ty jako programista traktujesz ten obiekt jako zniszczony i już. A to, czy pójdzie memset na zero czy inną debugową wartość czy nie - nie ma znaczenia, szczególnie dla początkujących.
0

Dziękuję wszystkim za odpowiedzi. Jak więc powinienem zmodyfikowac program? Bo próbowałem różnymi sposobami, zawsze coś jednak się nie zgadzało. ;(

JU
  • Rejestracja:około 22 lata
  • Ostatnio:2 miesiące
  • Postów:5042
0

Zdebuguj kod i zobaczysz, że błąd masz tu: g_game->init("Chapter 1", 100, 100, 640, 480, 0);
A teraz przeczytaj jeszcze raz mój post i zobacz, czego Ci brakuje. Przeczytaj też komentarz kq pod moim postem (RAII to te automatyczne wskaźniki).

I zapamiętaj - błąd typu AccessViolation zazwyczaj oznacza, że próbujesz dostać się do nieistniejącego obiektu.

edytowany 1x, ostatnio: Juhas
0

Temat do zamkniecia. Problem nie był ze wskaznikiem, tylko z niepotrzebną funkcją game() utworzoną w nagłówku. Dziekuje za rady i informacje ;)

fasadin
  • Rejestracja:prawie 14 lat
  • Ostatnio:prawie 3 lata
  • Postów:4882
0

oczywiscie ze problem jest z wskaznikiem. Nie wierze ze kod (ten z poczatku w main) wyglada tak samo teraz u Ciebie a to co tutaj nam pokazales.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.