Applikationen kraschar vid start, hittar inte felet.

Allmänt

Applikationen kraschar vid start, hittar inte felet.

Postby Kim Wahlman on Sat Apr 18, 2009 12:51 pm

Kompileraren ger mig 1 varning (att byta fopen till fopen_s) på varningsnivån 3. Annars så kompilerar koden men när man startar applikationen så kraschar den direkt.

main.cpp
Code: Select all
#include "main.h"
#include "render.h"
#include "core.h"

#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN

bool exiting = false;
long windowBit = 32;
bool fullscreen = false;

HWND Window;
HDC hDC;

Render *rrender = NULL;
Core *ccore = NULL;

void SetPixelFormat(HDC hDC)
{
   int pxFormat;
   PIXELFORMATDESCRIPTOR pfd =
   {
      sizeof(PIXELFORMATDESCRIPTOR), // Size,
      1,                        // Version,
      PFD_SUPPORT_OPENGL |         // OpenGL Window |
      PFD_DRAW_TO_WINDOW |         // render to window |
      PFD_DOUBLEBUFFER,            // support double buffering,
      PFD_TYPE_RGBA,               // Color type,
      32,                        // color depth,
      0, 0, 0, 0, 0, 0,            // color bits (ignored),
      1,                        // alpha buffer,
      0,                        // alpha bits (ignored),
      0,                        // no accumulation buffer,
      0, 0, 0, 0,                  // accum bits (ignored),
      16,                        // depth buffer,
      0,                        // no stencil buffer,
      0,                        // no auxiliary buffers
      PFD_MAIN_PLANE,               // main layer,
      0,                        // reserved,
      0,0,0,                     // no layer, visible, damage mask
   };
   pxFormat = ChoosePixelFormat(hDC, &pfd);
   SetPixelFormat(hDC, pxFormat, &pfd);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   static HDC hDC;
   static HGLRC hRC;
   int w, h;
   rrender = new Render();
   switch(msg)
   {
      case WM_CREATE:
         hDC = GetDC(hwnd);
         SetPixelFormat(hDC);
         hRC = wglCreateContext(hDC);
         wglMakeCurrent(hDC, hRC);
         break;

      case WM_DESTROY:
      case WM_QUIT:
      case WM_CLOSE:
         wglMakeCurrent(hDC, NULL);
         wglDeleteContext(hRC);
         PostQuitMessage(0);
         break;
      case WM_SIZE:
         h = HIWORD(lParam);
         w = LOWORD(wParam);
         // rrender->SetProjection(w, h); // Får applikation att krascha vid start. Variabeln 'w' är alltid 0 av någon anledning.
         break;
      default:
         break;
   }
   return (DefWindowProc(hwnd, msg, wParam, lParam));
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR lpCmdString, int CmdShow)
{
   WNDCLASSEX wc;
   MSG msg;
   /*
   DWORD dwExStyle;
   DWORD dwStyle;
   */
   RECT windowRect;

   windowRect.left      = (long)0;
   windowRect.right   = (long)wWidth;
   windowRect.top      = (long)0;
   windowRect.bottom   = (long)wHeight;

   wc.cbSize         = sizeof(WNDCLASSEX);
   wc.cbClsExtra      = 0;
   wc.cbWndExtra      = 0;
   wc.hbrBackground   = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
   wc.hCursor         = LoadCursor (NULL, IDC_ARROW);
   wc.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
   wc.hIconSm         = LoadIcon (NULL, IDI_APPLICATION);
   wc.hInstance      = hInstance;
   wc.lpfnWndProc      = WndProc;
   wc.lpszClassName   = "DME";
   wc.lpszMenuName      = NULL;
   wc.style         = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;


   if(!RegisterClassEx(&wc))
   {
      MessageBox(NULL,"Error: Cannot Register Class", "ERROR!", MB_OK);
      return 0;
   }

   AdjustWindowRect(&windowRect, WS_POPUP, FALSE);

   Window = CreateWindow("DME", "Divinus",
      WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, wWidth, wHeight, NULL, NULL, hInstance, NULL);

   hDC = GetDC(Window);

   /* Om fönstret inte kan skapas */
   if(!Window)
   {
      MessageBox(NULL,"Error: Failed to Create Window", "ERROR!", MB_OK);
      return 0;
   }

   ShowWindow(Window, SW_SHOW);
   UpdateWindow(Window);

      
   // ccore->initialyze(); // Kraschar applikationen vid start
      

   while (!exiting)
   {
      ccore->render;
      SwapBuffers(hDC);

      if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
      {
         if(!GetMessage(&msg, NULL, 0, 0))
         {
            exiting = true;
            break;
         }

         if(msg.message == WM_QUIT) break;
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }
      else
      {

      }
   }
   delete rrender;
   delete ccore;

   return (int)msg.wParam;
}


SetProjection
Code: Select all
void Render::SetProjection(int w, int h)
{
   if(h == 0) // Så vi inte dividerar med 0
      h = 1;

   glViewport(0, 0, w, h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(0, w, h, 0, 0, w > h ? w : h);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   
   core->render_screen();
}


render_screen()
Code: Select all
void Core::render_screen()
{
   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
   glLoadIdentity();
   for(int x = 19; x >= 0; x--) {
      for(int y = 19; y >= 0; y--) {
         if (tiles[x][y])
         {
            render->texture(x * 32, y * 32, pPlayer[x][y]->getGround());
            render->texture(x * 32, y * 32, objs[x][y]->getGround());
            render->texture(x * 32, y * 32, walls[x][y]->getGround());
            render->texture(x * 32, y * 32, tiles[x][y]->getGround());
         }
      }
   }
   glutSwapBuffers();
}


initialyze
Code: Select all
void Core::initialyze()
{
   glEnable(GL_DEPTH_TEST);
   glEnable(GL_TEXTURE_2D);
   glEnable(GL_BLEND);
   glAlphaFunc(GL_GREATER, 0);
   glEnable(GL_ALPHA_TEST);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   
   // Ladda sprites
   textures.push_back(render->loadBitmap("tiles/void.bmp"));                        // 0
   textures.push_back(render->loadBitmap("tiles/dirt.bmp"));                        // 1
   textures.push_back(render->loadBitmap("tiles/grass.bmp"));                        // 2
   textures.push_back(render->loadBitmap("tiles/rock.bmp"));                        // 3
   textures.push_back(render->loadBitmap("tiles/sand.bmp"));                        // 4
   textures.push_back(render->loadBitmap("tiles/water.bmp"));                        // 5
   textures.push_back(render->loadBitmap("tiles/stones.bmp"));                        // 6

   GLuint tTile;
   GLuint oTile;
   GLuint wTile;
   GLuint player;
   
   for(int x = 19; x >= 0; x--) {
      for(int y = 19; y >= 0; y--) {
         tTile = groundMap[y][x];
         oTile = objectMap[y][x];
         wTile = wallMap[y][x];
         player = playerLayer[y][x];

         tiles[x][y] = new Tile(textures[tTile]);
         walls[x][y] = new Tile(textures[wTile]);
         objs[x][y]  = new Tile(textures[oTile]);
         pPlayer[x][y] = new Tile(textures[player]);
      }
   }
}


core.h
Code: Select all
#ifndef _CORE_H_
#define _CORE_H_

#include "main.h"
#include "tile.h"
#include "render.h"

class Render;

class Core
{
   public:
      Core();
      virtual ~Core();

      void initialyze();    // Initierar 'kärnan(core)'
      void object();
      void render_screen(); // rendera skärmen
      void move(int key, int x, int y);
      Render *render;  // textur klassen
   protected:
      std::vector<unsigned int> textures;
      std::string double_to_string(double var); // double -> string

      void framerate(); // Kalkylera frameraten.

      Tile *tiles[20][20];
      Tile *objs [20][20];
      Tile *pPlayer[20][20];
      Tile *walls[20][20];

      int displayFPS;

      int frame;    // räkna framerate.
      double fps;     // actual framerate.
      int time;     // Håller i nuvarande tid.
      int timebase; // används för kalkylering av fps.
      int spx;
      int spy;
};

#endif


render.h
Code: Select all
#ifndef _RENDER_H_
#define _RENDER_H_

#include "main.h"
#include "tile.h"
#include "core.h"
#include <GL/glut.h> // header fil för GLUT.

class Render
{
   public:
      Render();
      virtual ~Render();

      unsigned int loadBitmap(const char* filename         ); // ladda texturen. (24-bit BMP)
      unsigned int loadBitmap(const char* filename, int alpha); // ladda texturen. (24-bit BMP)

      void texture(unsigned int x, unsigned int y, unsigned int id);                       // rendera en textur.
      void object(unsigned int x, unsigned int y, unsigned int id);                      // rendera ett object.
      void rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, int color); // rendera en rect.
      void text(unsigned int x, unsigned int y, void *font, int color, std::string text);   // rendera texten.
      void SetProjection(int w, int h);

   protected:
      unsigned int construct(GLenum format, unsigned char *data, unsigned long width, unsigned long height); // konstruera texturen.

      std::map<unsigned int, unsigned int> twidth;  // textur bredd.
      std::map<unsigned int, unsigned int> theight; // textur höjd.
};

#endif


Avlusaren ger mig detta.
Image

Med några breakpoints (jag är säker på hur man använder dessa men jag antar att jag gjorde rätt).
Image

Koden funkade perfekt i GLUT men när jag ändra till winapi så började detta problem uppstå, jag har ingen erfarenhet med winapi, läste en bok och ändrade på all deras kod till min kod.

Mitt nät var nere 2 veckor så jag har försökt få ihop detta men det går inte för mig.

Har försökt få hjälp på andra forum men ingen verkar veta varför det blir så här, eller hur man fixar detta. Enda någon sagt är 'uninitialized variable' eller 'trying to access uninitialized memory in an incorrect manner'. Eftersom jag inte hade några problem i GLUT och inte har några kunskaper inom winapi så förstår jag inte vad som är fel.

Kallar det winapi för jag inte vet om det kallas för något annat men jag antar att alla här vet vad jag menar med det.

Om någon här skulle vilja se all källkod så får ni säga till så skickar jag ett pm med en länk till ett zip arkiv med kod och dyligt för att öppna projektet i Visual Studio. Jag använder MS Visual Studio 2008.

Har bara en liten fråga till :D
Finns det någon möjlighet att få se era lokaler om någon kanske kan plåta hur klassrum etc ser ut. Så man vet vad som väntar på en när man söker om 2 år (måste plugga komvux först).

Tack för mig!
Kim Wahlman
 
Posts: 21
Joined: Thu Mar 13, 2008 2:26 pm
Location: Gävle
Nick: FrozenSnake

Re: Applikationen kraschar vid start, hittar inte felet.

Postby Jan-Peter.Nilsson on Sat Apr 18, 2009 2:23 pm

Nu har jag inte läst koden så jättenoga men det ser ut som att du aldrig instansierat core (this=0x0), detta i kombination med att försöka använda icke static funktioner och medlemsvariabler är nog anledningen till dina problem.
Jan-Peter.Nilsson
Instructor
 
Posts: 210
Joined: Fri Jul 21, 2006 8:11 am

Re: Applikationen kraschar vid start, hittar inte felet.

Postby Kim Wahlman on Sun Apr 19, 2009 10:12 am

Har nog tagit mig vatten över huvudet för tillfället, så hoppas jag kan luska ut hur man får rätsida på detta. Skall prova lite mer så får jag återkomma i tråden om jag inte kommer på något.

Tack för tipset!
Kim Wahlman
 
Posts: 21
Joined: Thu Mar 13, 2008 2:26 pm
Location: Gävle
Nick: FrozenSnake

Re: Applikationen kraschar vid start, hittar inte felet.

Postby Jan-Peter.Nilsson on Sun Apr 19, 2009 11:04 am

Det jag menar är alltså att någonstans mellan
Core *ccore = NULL;
och att du använder ccore behöver du initialisera den till att pekar på en instans av Core.
ccore = new Core();
Jan-Peter.Nilsson
Instructor
 
Posts: 210
Joined: Fri Jul 21, 2006 8:11 am

Re: Applikationen kraschar vid start, hittar inte felet.

Postby Fredrik Kuylenstierna on Sun Apr 19, 2009 2:37 pm

Varje gång du får en access violation så betyder det att din applikation försöker accessa minne som ligger utanför applikationens range.
Detta är väldigt farligt vad gäller pekare, då de "pekar" på en minnesadress som mycket väl kan vara oinitierad eller null.
En pekare i sig är i stort sett bara en "unsigned int" som håller en minnesadress, så att bara deklarera en pekare funkar inte. Den måste alltid riktas mot någonting för att fylla något funktion. Akta dig för att använda oinitierade pekare, för när du deklarerar en pekare (i release) så får det en adress som är helt random, vilket gör att om du använder den så använder den helt enkelt den data som råkar ligga på denna slumpmässiga minnesadress. Detta är en mardröm att felsöka.

Med andra ord: Sätt alltid dina pekare till NULL det första du gör när du deklarerat dom, och kolla alltid att dina pekare inte är NULL när du ska använda dom.
Kolla även att din pekare inte är NULL när du gett den ett värde. Minnet kanske tagit slut när du kallade "new" eller så kan något gått fel när objektet skapades genom ett funktionsanrop.

Råd: Dessa saker borde du ha god koll på innan du börjar med 3D. Mitt råd är att du håller dig till 2D-api;er (HGE, SFML, SDL) ett tag till. Gör ett par simpla spel och fokusera på dina c/c++ kunskaper. Lågnivå 3D-api;er såsom directX och openGL kräver en väldigt övergripande koll på vad som händer (spec openGL), och det kan vara för mycket för dig i detta skedet. Vill du tvunget arbeta i 3D så föreslår jag att du använder ett högnivå API såsom Ogre3D till att börja med. Det viktiga är att du är trygg i dina c/c++ kunskaper innan du tar åt dig för mycket. Att använda directX och openGL kräver dessutom god kunskap om kodstruktur för att hålla ordning i koden, annars blir det kaos, för det krävs mycket kod för att bygga ett framework runt ett lågnivå api.

Bara ett vänskapligt råd, ditt val...
“Just because nobody complains doesn't mean all parachutes are perfect.” -- Benny Hill
“Quotation is a serviceable substitute for wit.” -- Oscar Wilde (phun intended)
User avatar
Fredrik Kuylenstierna
Evil henchman #3
 
Posts: 260
Joined: Fri Jul 20, 2007 3:15 pm
Location: Asarum
Nick: Xarleth

Re: Applikationen kraschar vid start, hittar inte felet.

Postby Kim Wahlman on Sun Apr 19, 2009 3:31 pm

Jan-Peter.Nilsson wrote:Det jag menar är alltså att någonstans mellan
Core *ccore = NULL;
och att du använder ccore behöver du initialisera den till att pekar på en instans av Core.
ccore = new Core();

Tack kom förbi det där problemet, tänk att jag missade det och ingen jag bett hjälpa mig tidigare har sett det. Nu kan ja fortsätta med resten av problemen, som förhoppningsvis inte är lika svåra att hitta.

Fredrik Kuylenstierna wrote:Bara ett vänskapligt råd, ditt val...

Tack för tipsen :) spelet jag håller på med är i 2D inte 3D men jag ska kolla igenom koden så jag inte glömt det du sa på fler ställen och förhoppningsvis kunna lösa några problem själv =)
Kim Wahlman
 
Posts: 21
Joined: Thu Mar 13, 2008 2:26 pm
Location: Gävle
Nick: FrozenSnake

Re: Applikationen kraschar vid start, hittar inte felet.

Postby Henrik Danielsson on Sun Apr 19, 2009 3:50 pm

Lite förslag:
  • Lägg in ccore = new Core(); precis innan anropet till initialiseringen. Kontrollera kanske även att pekaren inte är NULL efter new Core(), så att konstruktorn verkligen kördes rätt.
  • I Core klassen har du en pekare till Render klassen (Core::render), och du har en global pekare till en instans av Render (rrender). Du behöver troligtvis bara den ena (Core::render) eftersom bara Core klassen använder den. Ta därför bort rrender och lägg till ccore->render = new Render(); efter ccore = new Core();. Annars kommer du nog få ett liknande fel i Core::render_screen(); Det är inte bra att skapa en instans av Render i WndProc eftersom den funktionen kallas av Windows så fort programmet får ett meddelande, vilket kan vara många gånger per frame. Varje gång skapas en ny instans av Render, utan att den gamla tas bort, det kommer snabbt att käka upp allt minne du har.
  • Core::render_screen() kallas aldrig (om inte Render::setProjection() körs). Jag antar att du vill kalla den varje gång en frame ska renderas, så byt ut ccore->render; (som inte gör något) mot ccore->render_screen(); i Message Loopen.
  • Core::render_screen() gör en glutSwapBuffers() så jag tror inte du behöver köra SwapBuffers(hDC); i Message Loopen. Risken är att du ritar till en buffert, swappar den mot den förra, och sen swappar tillbaka den och ritar på samma buffert igen utan att den förra ritades på.
  • Det kan bli lite skumt om du kör Core::render_screen() i Render::setProjection() då man kanske inte förväntar sig att skärmen ska ritas om direkt när man byter projektionsmatris, man kanske vill göra annat innan det ibland. Core och Render blir dessutom beroende av varandra, vilket oftast leder till spaghettikod där allt anropar allt. Det verkar som att du vill separera rendering från övrig logik (vilket oftast är bra) men låt då Core kontrollera Render och inte tvärt om eftersom Render "gör ett jobb åt" Core.
  • I Core::initialyze(), eller i samband med det, bör du anropa Render::setProjection() för att sätta en projektionsmatris, annars finns ingen satt när du kommer till första renderigsanropen och allt blir svart...
  • Ett senare tips kan vara att lägga meddelande hanteringen i en loop, så att så länge PeekMessage() returnerar att det finns ett meddelande fortsätter koden att beta av meddelandekön. Annars kan det hända att du får flera meddelanden per frame och de hinner aldrig komma ur kön eftersom det bara Dispatchas ett per frame. Lättaste sättet att lösa det på är nog att flytta ccore->render_screen(); (nuvarande ccore->render()) till else-delen av if(PeekMessage...). Då kan man vara säker på att du Dispatchar alla meddelanden i kön innan något renderas, så missar man tex inte spelarinput mm. Att hantera alla meddelanden tar bara en bråkdel av renderingstiden så du bör inte märka någon skillnad i hastighet, med bonusen att du kan vara väldigt säker på att spelet svarar när du gör något.
  • Tillbaks till core.h: Core-klassen har en pekare till Render klassen och inga anrop till en medlem av Render görs i core.h. Eftersom en pekare alltid är 4 bytes (iaf i 32 bit världen) behöver kompilatorn inte veta om vad som finns i Render klassen för att kunna skapa Core klassen. För att då slippa inkludera render.h i core.h (och därmed minska komplexiteten i koden och även sänka kompileringstiden) kan man använda sig av "forward declarations". Det är precis vad du redan gjort genom att bara skriva "class Render;" i core.h. Då vet kompilatorn att Render är en klass som faktiskt finns. Antagligen inkluderade du ändå render.h i core.h för att du annars fick problem när du försökte använda medlemmar ur Render i core.cpp. Eftersom vi bara sagt att Render är en klass, men inte vad den innehåller, i core.h (som inluderas av core.cpp) kommer kompilatorn till exempel till Core::render_screen() och ser anropet till render->texture(). Kompilatorn tror att Render är en tom klass och du får ett felmeddelande. För att fixa det behöver vi berätta för kompilatorn att vi i core.cpp faktiskt vill använda hela klassen och hur den ser ut. Det enda vi behöver för det är ett #include render.h i core.cpp. Eftersom core.cpp aldrig inkluderas någonstans finns det ingen risk för att det blir cirkulära includes som kan skapa väldigt konstiga fel. Aven om klasserna A, B, C osv alla behöver varandra och har anrop fram och tillbaka kommer det att fungera utan problem, så länge de använder sig av forward declarations i headern och bara inkluderar varandras headers i .cpp filerna. Om någon av dem har en hel instans och inte bara en pekare i klass-deklarationen måste man så klart fortfarande inkludera den andra klassens .h fil i headern...

Blev lite krångligt förklarat men ta det steg för steg så löser du det nog. Jag har säkert inte fått med allt ovan men det är en början.
Draco Dormien Nunquam Titillandus
FulCola.com
Henrik Danielsson
Site Admin
 
Posts: 816
Joined: Tue Aug 09, 2005 7:48 pm
Location: At work...
Nick: TwoD

Re: Applikationen kraschar vid start, hittar inte felet.

Postby Kim Wahlman on Sun Apr 19, 2009 5:18 pm

Henrik Danielsson wrote:Blev lite krångligt förklarat men ta det steg för steg så löser du det nog. Jag har säkert inte fått med allt ovan men det är en början.


Tack så mycket. Gör inget att det blev "lite krångligt förklarat" ska ju inte vara för lätt då lär jag mig ju inget. Ska läsa igenom ditt inlägg nu, och spara det så jag kan läsa det några gånger.
Kim Wahlman
 
Posts: 21
Joined: Thu Mar 13, 2008 2:26 pm
Location: Gävle
Nick: FrozenSnake


Return to SP: Allmänt

Who is online

Users browsing this forum: No registered users and 2 guests