Advertisement

Access Violation - Need Help

Started by June 23, 2003 11:54 AM
9 comments, last by ZMaster 21 years, 8 months ago
Hi, I have this access violation error when closing my 3D Demo. The rendering window disappears and I get the error message. I found out, that this must be caused somewhere in my 3DS loading code and since it occures when closing the program it might be caused by some memory freeing routine - but I don't know exactly if this is the problem (it only occures if I load a Model with Model::3DSLoad(), it doesn't if I dont load any!). I'm really frustrated - I tried to look up this error, a long time but I couldn't find anything. I'm stuck now and help would be really really great. Either it is just a stupid little mistake or it's a really complicated thing Some detailed information: Violation caused by: 0x77f4215c (don't know how to find the function call concerning this address) To Memory 0x00000000 could not be "written". Here's my 3DS Class Code if needed. MODEL is the class that holdes the model data (vertices etc.) and Model3DS is the Class that is responsible for loading 3DS Data to the MODEL structure.

//---------#> 3DS File Loader <#---------


#include "main.h"
#include "3ds.h"

//This is the Model class which holdes the object and material data of a model

MODEL::MODEL(void)
{
 tSkins = NULL;
 bHasDependencies = false;
 
 numOfObjects = 0;
 numOfMaterials = 0;
}

MODEL::~MODEL(void)
{
 if(tSkins && bHasDependencies)
  delete [] tSkins;
 
 tSkins = NULL;
 
 for(int i=0; i < numOfObjects; i++)
 {
  delete [] Object[i].Faces;
  delete [] Object[i].Normals;
  delete [] Object[i].TexVerts;
  delete [] Object[i].Verts;
 }
 
 numOfObjects = 0;
 numOfMaterials = 0;
}

bool MODEL::HasModel(void)
{
 if(numOfObjects > 0)
  return true;
 else
  return false;
}

bool MODEL::LoadDependencies(char *szPath)
{
 bool tmpRetVal = true; 
  
 if(HasModel())
 {
  tSkins = new Texture [numOfMaterials];
  
  for(int i=0; i < numOfMaterials; i++)
  {
   if(strlen(Materials[i].szFile) > 0)
   {
    char szTmpFile[255];
    wsprintf(szTmpFile, "%s%s", szPath, Materials[i].szFile);
    if(tSkins[i].LoadFromFile(szTmpFile) == false)
     tmpRetVal = false;
   }
   Materials[i].texID = i;
  }
 }
 
 bHasDependencies = true;
 return tmpRetVal;
}


void MODEL::Draw(void)
{
 for(int i=0; i < numOfObjects; i++)
 {
  if(Object.size() <= 0) break;
  if(Object[i].bHasTexture)
  {
   glEnable(GL_TEXTURE_2D);
   glColor3f(1.0, 1.0, 1.0);
   tSkins[Object[i].materialID].Bind();
   if(tSkins[Object[i].materialID].GetImageChannels() == 4)
   {
    glEnable(GL_ALPHA_TEST);
    glAlphaFunc(GL_GREATER, 0.5);
   }
  }
  else
  {
   glDisable(GL_TEXTURE_2D);
   glColor3f(1.0, 1.0, 1.0);
  }
  
  glBegin(GL_TRIANGLES);
   for(int t=0; t < Object[i].numOfFaces; t++)
   {
    for(int v=0; v < 3; v++)
    {
     int index = Object[i].Faces[t].vertIndex[v];
     
     glNormal3f(Object[i].Normals[index].x, Object[i].Normals[index].y, Object[i].Normals[index].z);
     if(Object[i].bHasTexture)
     {
      if(Object[i].TexVerts)
       glTexCoord2f(Object[i].TexVerts[index].x, Object[i].TexVerts[index].y);
     }
     else
     {
      if(Materials.size() && Object[i].materialID >= 0)
       glColor3f(float(Materials[Object[i].materialID].color[0]) / 256.0, float(Materials[Object[i].materialID].color[1]) / 256.0, float(Materials[Object[i].materialID].color[2]) / 256.0);
     }
     glVertex3f(Object[i].Verts[index].x, Object[i].Verts[index].y, Object[i].Verts[index].z);
    }
   }
  glEnd();
  
  glDisable(GL_ALPHA_TEST);
 }
} 

void MODEL::PrivateGetBoundingSphere(Vector3 *center, float *radius)
{
 float hx = 0.0, hy = 0.0, hz = 0.0;
 
 for(int i=0; i < numOfObjects; i++)
 {
  for(int n=0; n < ObjectArrays[i].VertexCounter * 3; n += 3)
  {
  
   if(ObjectArrays[i].Vertices[n + 0] > hx)
    hx = ObjectArrays[i].Vertices[n + 0];
   if(ObjectArrays[i].Vertices[n + 0] > hy)
    hy = ObjectArrays[i].Vertices[n + 1];
   if(ObjectArrays[i].Vertices[n + 0] > hz)
    hz = ObjectArrays[i].Vertices[n + 2];
    
  }
 }
 
 Vector3 tmp;
 tmp.x = hx / 2;
 tmp.y = hy / 2;
 tmp.z = hz / 2;
 
 if(hx > hy && hx > hz)
  *radius = hx * 2;
 else if(hy > hx && hy > hz)
  *radius = hy * 2;
 else
  *radius = hz * 2;
  
 *center = tmp; 
}

void MODEL::GetBoundingSphere(Vector3 *center, float *radius)
{
 *center = vCenter;
 *radius = fRadius;
}

void MODEL::GetBoundingSphere(float *x, float *y, float *z, float *radius)
{
 *x = vCenter.x;
 *y = vCenter.y;
 *z = vCenter.z;
 *radius = fRadius;
}



//The Model3DS Class which is responsible for loading 3DS model files

Model3DS::Model3DS(void)
{
 currentChunk = new CHUNK;
 currentChunk->bytesRead = 0;
 currentChunk->length = 0;
 
 tmpChunk = new CHUNK;
 tmpChunk->bytesRead = 0;
 tmpChunk->length = 0;
 
 bChangeAxis = true;
}

Model3DS::~Model3DS(void)
{

}

bool Model3DS::Load(MODEL *Model, char *szFilename)
{
 char szMessage[255] = {0};
 file = fopen(szFilename, "rb");
 
 if(!file)
 {
  wsprintf(szMessage, "Error loading 3DS file: %s", szFilename);
  MessageBox(NULL, szMessage, "Error", MB_OK | MB_ICONERROR);
  return false;
 }
 
 ReadChunk(currentChunk);
 
 if(currentChunk->ID != PRIMARY)
 {
  wsprintf(szMessage, "Not a 3DS file: %s", szFilename);
  MessageBox(NULL, szMessage, "Error", MB_OK | MB_ICONERROR);
  return false;
 }
 
 ProcessNextChunk(Model, currentChunk);
 ComputeNormals(Model);
 CleanUp();
 
 return true;
}

void Model3DS::CleanUp(void)
{
 fclose(file);
 
 delete currentChunk;
 delete tmpChunk;
}

void Model3DS::ProcessNextChunk(MODEL *Model, CHUNK *previousChunk)
{
 OBJECT_INFO newObject = {0};
 MATERIAL_INFO newTexture = {0};
 unsigned int version = 0;
 int buffer[50000] = {0};
 
 currentChunk = new CHUNK;
              
 while(previousChunk->bytesRead < previousChunk->length)
 {
  ReadChunk(currentChunk);
      
  switch(currentChunk->ID)
  {
   case VERSION:
    currentChunk->bytesRead += fread(&version, 1, currentChunk->length - currentChunk->bytesRead, file);
    if(version > 0x03)
     MessageBox(NULL, "The 3DS file is newer than version 3.\n It may load incorrectly!", "Warning", MB_OK | MB_ICONEXCLAMATION);
     
   break;
   case OBJECTINFO:
    ReadChunk(tmpChunk);
    tmpChunk->bytesRead += fread(&version, 1, tmpChunk->length - tmpChunk->bytesRead, file);
    currentChunk->bytesRead += tmpChunk->bytesRead;
    ProcessNextChunk(Model, currentChunk);
   break;
   case MATERIAL:
    Model->numOfMaterials++;
    Model->Materials.push_back(newTexture);
    ProcessNextMaterialChunk(Model, currentChunk);
   break;
   case OBJECT:
    Model->numOfObjects++;
    Model->Object.push_back(newObject);
    memset(&(Model->Object[Model->numOfObjects - 1]), 0, sizeof(OBJECT_INFO));
    currentChunk->bytesRead += GetString(Model->Object[Model->numOfObjects - 1].szName);
    ProcessNextObjectChunk(Model, &(Model->Object[Model->numOfObjects - 1]), currentChunk);
   break;
   default:
    currentChunk->bytesRead += fread(buffer, 1, currentChunk->length - currentChunk->bytesRead, file);
   break;
  }
  
  previousChunk->bytesRead += currentChunk->bytesRead;
 }
 
 delete currentChunk;
 currentChunk = previousChunk;
}

void Model3DS::ProcessNextObjectChunk(MODEL *Model, OBJECT_INFO *Object, CHUNK *previousChunk)
{
 int buffer[50000] = {0};
 
 currentChunk = new CHUNK;
 
 while(previousChunk->bytesRead < previousChunk->length)
 {
  ReadChunk(currentChunk);
  
  switch(currentChunk->ID)
  {
   case OBJECTMESH:
    ProcessNextObjectChunk(Model, Object, currentChunk);
   break;
   case OBJECT_VERTICES:
    ReadVertices(Object, currentChunk);
   break;
   case OBJECT_FACES:
    ReadVertexIndices(Object, currentChunk);
   break;
   case OBJECT_MATERIAL:
    ReadObjectMaterial(Model, Object, currentChunk);
   break;
   case OBJECT_UV:
    ReadUVCoordinates(Object, currentChunk);
   break;
   default:
    currentChunk->bytesRead += fread(buffer, 1, currentChunk->length - currentChunk->bytesRead, file);
   break;
  }
  
  previousChunk->bytesRead += currentChunk->bytesRead;
 }
 
 delete currentChunk;
 currentChunk = previousChunk;
}

void Model3DS::ProcessNextMaterialChunk(MODEL *Model, CHUNK *previousChunk)
{
 int buffer[50000] = {0};
 
 currentChunk = new CHUNK;
 
 while(previousChunk->bytesRead < previousChunk->length)
 {
  ReadChunk(currentChunk);
  
  switch(currentChunk->ID)
  {
   case MATNAME:
    currentChunk->bytesRead += fread(Model->Materials[Model->numOfMaterials - 1].szName, 1, currentChunk->length - currentChunk->bytesRead, file);
   break;
   case MATDIFFUSE:
    ReadColorChunk(&(Model->Materials[Model->numOfMaterials - 1]), currentChunk);
   break;
   case MATMAP:
    ProcessNextMaterialChunk(Model, currentChunk);
   break;
   case MATMAPFILE:
    currentChunk->bytesRead += fread(Model->Materials[Model->numOfMaterials - 1].szFile, 1, currentChunk->length - currentChunk->bytesRead, file);
   break;
   default:
    currentChunk->bytesRead += fread(buffer, 1, currentChunk->length - currentChunk->bytesRead, file);
   break;
  }
  
  previousChunk->bytesRead += currentChunk->bytesRead;
 }
 
 delete currentChunk;
 currentChunk = previousChunk;
}

void Model3DS::ReadChunk(CHUNK *Chunk)
{
 Chunk->bytesRead = 0;
 Chunk->bytesRead += fread(&Chunk->ID, 1, 2, file);
 Chunk->bytesRead += fread(&Chunk->length, 1, 4, file);
}

int Model3DS::GetString(char *buffer)
{
 int index = 0;
 fread(buffer, 1, 1, file);
 
 while(*(buffer + index++) != 0)
 {
  fread(buffer + index, 1, 1, file);
 }
 
 return strlen(buffer) + 1;
}

void Model3DS::ReadColorChunk(MATERIAL_INFO *Material, CHUNK *Chunk)
{
 ReadChunk(tmpChunk);
 tmpChunk->bytesRead += fread(Material->color, 1, tmpChunk->length - tmpChunk->bytesRead, file);
 Chunk->bytesRead += tmpChunk->bytesRead;
}

void Model3DS::ReadVertexIndices(OBJECT_INFO *Object, CHUNK *previousChunk)
{
 unsigned short index = 0;
 
 previousChunk->bytesRead += fread(&Object->numOfFaces, 1, 2, file);
 
 Object->Faces = new FACE [Object->numOfFaces];
 memset(Object->Faces, 0, sizeof(FACE) * Object->numOfFaces);
 
 for(int i=0; i < Object->numOfFaces; i++)
 {
  for(int j=0; j < 4; j++)
  {
   previousChunk->bytesRead += fread(&index, 1, sizeof(index), file);
   
   if(j < 3)
   {
    Object->Faces[i].vertIndex[j] = index;
   }
  }
 }
}

void Model3DS::ReadUVCoordinates(OBJECT_INFO *Object, CHUNK *previousChunk)
{
 previousChunk->bytesRead += fread(&Object->numTexVertex, 1, 2, file);
 
 Object->TexVerts = new Vector2 [Object->numTexVertex];
 previousChunk->bytesRead += fread(Object->TexVerts, 1, previousChunk->length - previousChunk->bytesRead, file);
}

void Model3DS::ReadVertices(OBJECT_INFO *Object, CHUNK *previousChunk)
{
 previousChunk->bytesRead += fread(&(Object->numOfVerts), 1, 2, file);
 
 Object->Verts = new Vector3 [Object->numOfVerts];
 memset(Object->Verts, 0, sizeof(Vector3) * Object->numOfVerts);
 
 previousChunk->bytesRead += fread(Object->Verts, 1, previousChunk->length - previousChunk->bytesRead, file);
 
 if(bChangeAxis)
 {
  for(int i=0; i < Object->numOfVerts; i++)
  {
   float tmpY = Object->Verts[i].y;
   Object->Verts[i].y = Object->Verts[i].z;
   Object->Verts[i].z = -tmpY;
  }
 }
}

void Model3DS::ReadObjectMaterial(MODEL *Model, OBJECT_INFO *Object, CHUNK *previousChunk)
{
 char szMaterial[255] = {0};
 int buffer[50000] = {0};
 
 previousChunk->bytesRead += GetString(szMaterial);
 
 for(int i=0; i < Model->numOfMaterials;  i++)
 {
 
  if(strcmp(szMaterial, Model->Materials[i].szName) == 0)
  {
   Object->materialID = i;
   if(strlen(Model->Materials[i].szFile) > 0)
   {
    Object->bHasTexture = true;
   }
   break;
  }
  else
  {
   Object->materialID = -1;
  }
  
 }
 
 previousChunk->bytesRead += fread(buffer, 1, previousChunk->length - previousChunk->bytesRead, file);
}

void Model3DS::ComputeNormals(MODEL *Model)
{
 Vector3 vVector1, vVector2, vNormal, vTriangle[3];
 
 if(Model->numOfObjects <= 0)
  return;
  
 for(int index=0; index < Model->numOfObjects; index++)
 {
  OBJECT_INFO *Object = &(Model->Object[index]);
  
  Vector3 *Normals = new Vector3 [Object->numOfFaces];
  Vector3 *tmpNormals = new Vector3 [Object->numOfFaces];
  Object->Normals = new Vector3 [Object->numOfVerts];
  
  for(int i=0; i < Object->numOfFaces; i++)
  {
   vTriangle[0] = Object->Verts[Object->Faces[i].vertIndex[0]];
   vTriangle[1] = Object->Verts[Object->Faces[i].vertIndex[1]];
   vTriangle[2] = Object->Verts[Object->Faces[i].vertIndex[2]];
   
   vVector1 = Distance(vTriangle[0], vTriangle[2]);
   vVector2 = Distance(vTriangle[2], vTriangle[1]);
   
   vNormal = CrossProduct(vVector1, vVector2);
   tmpNormals[i] = vNormal;
   vNormal = Normalize(vNormal);
   
   Normals[i] = vNormal;
  }
  
  Vector3 vSum;
  vSum.x = 0.0; vSum.y = 0.0; vSum.z = 0.0;
  Vector3 vZero = vSum;
  int shared = 0;
  
  for(int i=0; i < Object->numOfVerts; i++)
  {
   for(int j=0; j < Object->numOfFaces; j++)
   {
    if(Object->Faces[j].vertIndex[0] == i || Object->Faces[j].vertIndex[1] == i || Object->Faces[j].vertIndex[2] == i)
    {
     vSum = AddVector(vSum, tmpNormals[j]);
     shared++;
    }
   }
   
   Object->Normals[i] = DivideVector(vSum, float(-shared));
   Object->Normals[i] = Normalize(Object->Normals[i]);
   
   vSum = vZero;
   shared = 0;
  }
  
  delete [] tmpNormals;
  delete [] Normals;
 }
}

void Model3DS::UnLoad(MODEL *Model)
{
 Model->~MODEL();
}
 
[edited by - ZMaster on June 23, 2003 12:56:31 PM] [edited by - ZMaster on June 23, 2003 12:58:35 PM]
I''m sooo sure its in the destructor where you delete stuff.
Try commenting it out, in Debug mode, and run it. It shouldn''t crash, but there goes another memory leak.
I think it''s 1 of the n deletes, not all of them.

Answer might be: Init your pointers to NULL! That should do it!

.lick
Advertisement
I just figured that I''m the smartest human being in my City. Cool!
Thank me if it works.. I''d love that..
You too?! It is a great feeling is it not?
Ok, thanks. I can''t believe that it is in one of the destructors because I already commented them out for debugging, but what I''ll try tomorrow is, that I will search for all delete [] commands and check wether they are fully correct or not. But maybe still somebody can find anything incorrect in my code. What do you mean by initializing my pointers to NULL. I know how to do that and what that means, but I''m not quite sure WHERE in my code I should initialize them to NULL. Do you mean before allocating memory for my pointers and giving them a value or right after freeing the memory so that they are reinitialized to NULL?

So what''s that thing with the smartest kid in town? Is it a joke or a serious thing? So if thats serious - Congratulations


I didnt have time to read though all the code, but i was thinking what pipo said, initallize your pointers to NULL. Always do that with pointers as when you declair them they have junk data, which can point to a adress. This adress by try and be deleted durring the cleanup and thus your problem.

Where ever you declair your pointers set them equil to NULL;

IE

int * blah = NULL;


To use NULL you need to include the standard library for c++.

Hope that helps, pardon my horrible spelling i got a huge headache and am to lazy to check it


[edited by - skow on June 23, 2003 4:55:33 PM]
Advertisement
Look, I mean to NULLify the pointers you use for new/delete in the constructor!

.lick
quote:
Original post by skow
To use NULL you need to include the standard library for c++.



You know, you could always just use 0.


Death of one is a tragedy, death of a million is just a statistic.
If at first you don't succeed, redefine success.
Yes, you could always use o and 1 for true and falses aswell...

Just becuase you can do somthing easier, doesnt mean its alwas better
Could just as well be that you''re overwriting some buffer, and some other free-ing thing is crashing trying to free a memory block whose header you clobbered.

If it''s always the same address, try setting a watchpoint on that address.

Try setting a breakpoint and stepping through the shutdown of your program. Step into all functions.

Make sure you compile with symbols enabled, even in release mode, by the way. Install sources for all libraries, so you can step into them. Learn how to read disassembly so you can look back the code stream to see where your pointer came from, and look up the stack to see where the appropriate return addresses live.

Always use Purify.

This topic is closed to new replies.

Advertisement