Crash caused by texture lock

Started by
5 comments, last by Dave Hunt 19 years, 5 months ago
I've had this problem for some time now, but it appears to be more common on some computers than others. In the multiplayer portion of my game, there's a small chat box for communicating with the other player. Instead of using any text functions built into Direct 3D, I decided this whole thing would be much easier if I just draw all my text onto a Windows GDI surface, and then blit it into a DX texture which is mapped on a square on screen as the chat window. This works fine most of the time. The catch is, every time you type and send a message, there's a really tiny chance that the game will crash. [oh] The nature of the crash is the most frustrating thing. I get an access violation when I call SetTexture, but here's the weird part. It doesn't always crash with the chatbox's texture! More often, it's when I try to draw the actual level itself that SetTexture crashes! Debug shows that the texture pointer in question always appears valid (non-null, at least) and I certainly hadn't messed with it since the previous frame when it worked fine, but it crashes. Expirementation has shown it always crashes when you either send or receive a message, meaning it could be in the release of the chat message texture, or more likely the locking of the main chat window texture to draw the new message. Hopefully I've made the problem clear. Here's a bit of code. I know this thing can sometimes be caused by a memory overwrite in managed texture memory, but I sure don't see one. Maybe I just need a third-party sanity check, but I don't have a spare D3D programmer lying around to do one for me. [looksaround] The locking code:

   tb->tex->lpVtbl->LockRect(tb->tex,0,&rect,NULL,0);
   bits=rect.pBits;
   for(y=0;y<tb->h;y++)
   {
      for(x=0;x<tb->w;x++)
      {
         c=GetPixel(tb->dc,x,y);
         if((c&0xFFFFFF)==(unsigned)(tb->bgcolor&0xFFFFFF))bits[y*rect.Pitch+x*4+3]=(BYTE)((tb->bgcolor&0xFF000000)>>24);
         else bits[y*rect.Pitch+x*4+3]=(BYTE)((tb->color&0xFF000000)>>24);
         bits[y*rect.Pitch+x*4]=(BYTE)(c&0xff);
         bits[y*rect.Pitch+x*4+1]=(BYTE)((c&0xff00)>>8);
         bits[y*rect.Pitch+x*4+2]=(BYTE)((c&0xff0000)>>16);
      }
   }
   tb->tex->lpVtbl->UnlockRect(tb->tex,0);
   unlock(tb);

tb->dc is a WinGDI Device Context that points to a windows bitmap object of the same width and height as the texture. In case anyone's confused by that first blit line with the if statement, basically the background color of the window is slightly more transparent than the text color. The texture for blitting is created with the following line: D3DXCreateTexture(device,tb->w,tb->h, 1,0,D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,&tb->tex); Any idea what could be happening here?
VideoWorks Softwarehttp://www.3dpoolpro.com
Advertisement
I notice that you're not doing any error checking. It could be that LockRect() is failing and/or rect.pBits is NULL.

Also, I see an unlock(tb), but I don't see a corresponding lock(tb). That may just be an oversight in your cut-and-paste. Perhaps something in your unlock is releasing something it shouldn't.
Oh yeah, sorry about that "unlock" thing. That's supposed to be for thread safety, though this function shouldn't be called from a thread. Better safe than sorry. The matching "lock" was way at the top of the function, above a bunch of GDI code that you don't want to see.
Thanks. I'll check those return values and see if I get anything unexpected. But if I did get something unexpected, I would then be at a loss as to WHY it happened.
VideoWorks Softwarehttp://www.3dpoolpro.com
Ok,I've put in the error checks after those lines and managed to recreate this bug several times. Not even once did I get anything besides S_OK and a valid pointer out of that lock.

The crash happens on the lock statement itself, sometimes, but more often when I try to draw my main background model, which is unrelated. It's almost like, when I take out a lock for an extended time, suddenly one of my other textures gets clobbered. (The specific line is a SetTexture on a texture loaded with the main scene model file.) Maybe also the release function that I'm calling on the chat window is releasing more than it should? The texture creation function is above. The release is just:

tb->tex->lpVtbl->Release(tb->tex);

Does anybody else see anything wrong here?
VideoWorks Softwarehttp://www.3dpoolpro.com
From a code execution stand-point, is there a 1-to-1 correlation between your CreateTexture and Release? Also, are you creating/releasing your chat message texture each frame? That doesn't sound like a good idea.

At any rate, it sounds like you're trying to access a texture that has been released (in which case, the pointer might "look" good, but still be invalid).
Yep, that's what I was thinking, but as usual the problem was elsewhere and I didn't post enough code to allow someone to catch it for me. [embarrass]

Thanks for the good advice, though, it did help me narrow things down.

BTW, I'm only locking and redrawing when the text window gets modified in some way. This is slowish, especially when you're holding down the scroll button, but it's plenty fast enough to keep up with typing.

For the curious, the problem was that I was clipping my text messages to 256 bytes before sending them, because that was my maximum packet buffer size. With this:

str[255]=0;

The catch was, str was a dynamicly allocated string, not the static strings I'm usually more fond of, so a simple addition of
if(strlen(str)>255)str[255]=0;
in an entirely different source file fixed the bug. Previously that zero was occassionally overwriting part of the texture pointer just before it got released, causing the program to release a random other texture instead.

The good news is, it's fixed, and my buglist is now officially empty. [cool]
VideoWorks Softwarehttp://www.3dpoolpro.com
Don't you just hate that!?

Congrats on getting it resolved. Glad to have been of little use whatsoever. ;)

This topic is closed to new replies.

Advertisement