gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

OffTopic > c++: glibc memmory corruption

#132234 - Mr Snowflake - Sun Jun 24, 2007 10:36 pm

*** EDIT see below ***

Hi guys,

I'm working on a .bsp (V30 - half-life) loader/renderer. But when I try to allocate some memory on the heap I get a: *** glibc detected *** /home/mrsnowflake/Projects/c/snow3d/debug/src/snow3d: malloc(): memory corruption: 0x0810a5c0 ***. I tried it on my desktop and on my laptop, but they both give the same error. Both my computers are running ubuntu, so maybe I should try some other os.

This is the code genereting the error:
Code:
      planes = new Plane[header->planes.size/sizeof(Plane)];
      if(!readLump(planes, header->planes.offset, header->planes.size))
         return false;
      //textureLumpHeader = &header + header->directory[LUMP_FACES].offset;
      //mipTex = &header + header->directory[LUMP_FACES].offset;
      vertices = new Vertex_t[header->vertices.size/sizeof(Vertex_t)];
      if(!readLump(vertices, header->vertices.offset, header->vertices.size))
         return false;
      listOfFaces = new faceList[header->lface.size/sizeof(faceList)];
      if(!readLump(listOfFaces, header->lface.offset, header->lface.size))
         return false;
      listOfEdges = new surfedge[header->ledges.size/sizeof(surfedge)];
      if(!readLump(listOfEdges, header->ledges.offset, header->ledges.size))
         return false;
      nodes = new Node[header->nodes.size/sizeof(Node)];
      if(!readLump(nodes, header->nodes.offset, header->nodes.size))
         return false;
      //texInfo = &header + header->directory[LUMP_FACES].offset;
      faces = new Face[header->faces.size/sizeof(Face)];
      if(!readLump(faces, header->faces.offset, header->faces.size))
         return false;
      leaves = new Leaf[header->leaves.size/sizeof(Leaf)];
      if(!readLump(leaves, header->leaves.offset, header->leaves.size))
         return false;
      clipNode = new ClipNode[header->clipnodes.size/sizeof(ClipNode)];
      if(!readLump(clipNode, header->clipnodes.offset, header->clipnodes.size))
         return false;
      edges = new Edge[header->edges.size/sizeof(Edge)];
      if(!readLump(edges, header->edges.offset, header->edges.size))
         return false;
      models = new Model[header->models.size/sizeof(Model)];
      if(!readLump(models, header->models.offset, header->models.size))
         return false;

the readLump reads some data from a file. The program usely crashes at clipNode = new ClipNode[header->clipnodes.size/sizeof(ClipNode)]; Does any one as an idea why this is happening?

I just discovered the issue only exists when I setup SDL first. If I comment all the SDL stuff the allocation runs perfectly, but when I just SDL_Init( SDL_INIT_VIDEO ) the problem exists.

EDIT: Well, I think it's a SDL problem. When I load the map before I setup SDL, the code crashes when gdb gets at SDL_Init( SDL_INIT_VIDEO )... So I probably need to fix sdl or work around sdl...
_________________
http://www.mrsnowflake.be

#132256 - chishm - Mon Jun 25, 2007 3:11 am

I found those errors can be caused much earlier in the program. I ran into this problem once when I accidentally overflowed a malloc'd buffer. The actual error didn't show up until much later, when I tried to free a different buffer.
_________________
http://chishm.drunkencoders.com
http://dldi.drunkencoders.com

#132274 - Mr Snowflake - Mon Jun 25, 2007 12:12 pm

With your reply in mind, I tried to allocate a 'fail-safe' buffer between my file reading stuff and the sdl stuff. And now the program works...
Code:
   try{
      test = new char[1<<shiftNum];
   }catch(...){
      cerr << "New gecatched\n";
   }
The thing is: when shiftNum == 30 I catch an error. When shiftNum == 20 I get a segmentation fault and when shiftNum == 10 I get this: *** glibc detected *** /home/mrsnowflake/Projects/c/snow3d/debug/src/snow3d: free(): invalid next size (fast): 0x0804eb30 *** Which is the same error when doing the file load before the SDL init.

Strange stuff.
_________________
http://www.mrsnowflake.be

#132290 - ps2aich - Mon Jun 25, 2007 3:54 pm

Mr Snowflake wrote:
With your reply in mind, I tried to allocate a 'fail-safe' buffer between my file reading stuff and the sdl stuff. And now the program works...
Code:
   try{
      test = new char[1<<shiftNum];
   }catch(...){
      cerr << "New gecatched\n";
   }
The thing is: when shiftNum == 30 I catch an error. When shiftNum == 20 I get a segmentation fault and when shiftNum == 10 I get this: *** glibc detected *** /home/mrsnowflake/Projects/c/snow3d/debug/src/snow3d: free(): invalid next size (fast): 0x0804eb30 *** Which is the same error when doing the file load before the SDL init.

Strange stuff.


I only know such strange things happen when mixing debug and non debug built libraries. Usually, in debug builds, the malloc/new handler inserts kinds of sentinel bytes between allocated memory blocks to detect illegal write accesses.
So, if memory is allocated in non debug build lib and deallocated in debug-build code, maybe memory corruption is detected (since the sentinel bytes are not there) OR memory is corrupted itself, sind the deallocation nulls out imaginary sentinel bytes.

#132372 - Mr Snowflake - Tue Jun 26, 2007 9:21 am

That sounds pretty believable. But I changed my code back to the original state: meaning, I now read the whole file, well, I'll eventually read only the world stuff I need and then stream the textures. So now I don't have the allocation problem any more. But thanks any way, if/when I encounter this problem again, I'll check if building a default or maybe optimized binary helps solving this problem.

[edit]Solved[/edit]
[strike]Now I have another question: Say I need to load this struct from a file:
Code:

struct TextureLumpHeader{
  unsigned long numTex;      // Number of miptex structures
  unsigned long offset[numTex];
};

What is the best way of doing this. At the moment, like I said, I load the whole file in unsigned byte* data. So I can get the memory location for the TextureLumpHeader struct by doing (TextureLumpHeader*)(data+header->textLumpOffset). With header->textLumpOffset being just the offset in the file.
This code doesn't work, as I can't allocate offset[numTex] because numTex is unknow. That's why I changed offset to a unsigned long*. But I can't access offset that way either it's rendering a segmentation fault. I tried setting offset myself to (unsigned long*)(data+header->textLumpOffset+sizeof(unsigned long)) but this still isn't working...[/strike]
_________________
http://www.mrsnowflake.be