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.

Coding > Binary Amnesia (Witty title for a confusing memory bug)

#476 - staringmonkey - Wed Jan 08, 2003 1:30 am

Hey all,

For anybody who wants to hit me with the "where the hell have you been, we never talk to you anymore" style questions, you can go ahead, but thats not the reason for this post. :)
Normally I'd post my problems on the Yahoo group, but I thought I'd give these handy dandy new message boards a spin.

Heres the situation:

Basically, I've run out of IWRAM and I don't know why. But let me start at the beginning. The last few coding sessions I've had I've been having variables return incorrectly, AKA the values in the variables are fine within the function, but when returned and stored in a variable the value is corrupted. I thought that I was just doing something stupid so I took some time off from that and did some optimization stuff, but yesterday when I went back to work on it I started having the same problem. I didn't know what could be causing it other than some sort of memory bug so I just checked the address of one of my most recently initialized variables to see where it was in memory and it was at 0x3007d73, right on the trailing edge of IWRAM! I can more or less put together the pieces on whats going on here, but I don't understand where my RAM could have gone. All my game data is in ROM and my game variables are in EXRAM (granted the pointers to them are in IWRAM, but thats not much). According to my .map file my last global is being placed at 0x030007a8, not even 2K into RAM. So the only things in memory are code, 2K of globals, and local variables... that can't account for 32K worth of RAM. I don't understand what the rest of my memory is being used for.
For the sake of experimentation (the way I usually find solutions to bugs) I tried declaring a variable right at the beginning of my first function to see where it was getting put. Address check: 0x3007ef4. So basically I'm missing the vast majority of IWRAM... I won't claim to having ever been an expert on low-level memory management, but never-the-less I've never seen anything like this.

Any ideas what the hell is going on? BTW, this is for a professional project with an upcoming deadline, so time is severely NOT on my side.

Thanks in advance,
staringmonkey

#483 - ampz - Wed Jan 08, 2003 1:53 am

That's your stack.
The stack is usually placed at the end of the memory area.
Local variables goes onto the stack you know.

#485 - staringmonkey - Wed Jan 08, 2003 2:14 am

Ampz:

Ahhhhhhhh (sigh of understanding). I didn't know the stack was placed at the end of memory. Well that makes sense. Tid-bit of knowledge that I did not know. So then my problem may not be a memory issue after all. Then why are my functions returning incorrect values...?

I guess I'll go tinker with this code some more... maybe it was something stupid I was doing after all... :)

Thanks,
staringmonkey

#487 - Touchstone - Wed Jan 08, 2003 2:21 am

If you have the official devkit hardware you can use the debugger to single-step each assembly instruction and that way follow your data from one function to the next more closely than by single-stepping each C line. If you don't have the debug hardware on the other hand you're .. how should I put this .. on your own.
_________________
You can't beat our meat

#488 - theSparko - Wed Jan 08, 2003 2:34 am

I am a total Noob to GBA development, but I know some programming and I thought this sounded like a bug that might deal with passing by value or reference.

Y'know:
Code:

void swap(int x, int y) {
     int temp = x;
     x = y;
     y = temp;
     return;
}


Now if you check the value of x and y they're still their original values because C is pass by value. So the function gets the values of x and y not a reference to their addresses.

Anyway, I'm sure you probably already thought of this, but I thought I'd throw it out there anyway just cause I like to help people.

Helpfully,
theSparko

#506 - tom - Wed Jan 08, 2003 7:47 am

staringmonkey wrote:

So then my problem may not be a memory issue after all. Then why are my functions returning incorrect values...?
staringmonkey


post one of these functions. perhaps you're returning addresses of local variables on the stack ?

#507 - staringmonkey - Wed Jan 08, 2003 7:50 am

Hey guys,

TouchStone: No I don't have official dev-hardware, not yet anyway.

theSparko: Not quite what I was asking for, but thanks for trying to be helpful. :)

Normally I wouldn't post code, but this is an extenuating (sp?) circumstance:

Code:

///////////////////////////////Output////////////////////////////////////////
u8 Output(u8 screenMem, u16 font, u8 palette, u8 startX, u8 startY, u8 maxX, u8 maxY, char *originalString, ...)
{
   //Local variables
   u16 i = 0;                                 //Looping variable
   u8 x = 0;                                 //X Column
   u8 y = 0;                                 //Y Row
   char outputString[(strlen(originalString) + 32)];   //String with variables
   u16 length = 0;                              //Array length
   u16 currentLetter = 0;                        //Current letter
   u16 *destination = 0;                        //Target memory
   u16 findSpace = 0;                           //Used to find last space before line-end

   //Cocanate variables into this string
   va_list arguments;                              //Get arguments list
   va_start(arguments, originalString);               //Start
   vsprintf(outputString, originalString, arguments);      //Copy arguments
   va_end(arguments);                              //End

   //Get the target memory
   destination = GET_SCREEN_MEM(screenMem);

   //Get the length of the string
   length = strlen(outputString);

   //Starting cursor position
   x = startX;
   y = startY;

   //Output the text
   for(currentLetter = 0; currentLetter < length; currentLetter++)
   {
      //This letter is a carriage return
      if(outputString[currentLetter] == TEXT_CR)
      {
         //Next line
         x = startX;
         y++;

         //Next letter
         continue;
      }

      //If past the end of this line
      if(x >= maxX)
      {
         //Start at currentLetter
         findSpace = currentLetter;

         //Search string
         while(outputString[findSpace] != TEXT_SPACE)
         {
            //Backwords from current point
            findSpace--;

            //No spaces found in the sentence
            if(findSpace <= 0)
            {
               //Just start writing on the next line with this letter
               findSpace = currentLetter - 1;

               break;
            }
         }

         //Move forward from the found space
         for(i = findSpace + 1; i < currentLetter; i++)
         {
            //Erase this letter
            destination[(y * 32) + (x - (currentLetter - i))] = 0;
         }
            
         //Beginning of next line
         x = startX;
         y++;

         //Move back in the string (just past the space) and start writing again
         currentLetter = findSpace + 1;

         //Past maximum length
         if(y >= maxY)
         {
            //Quit writing
            return (y + 1);
         }
      }
   
      //Output the current letter
      destination[(y * 32) + (x)] = ((font + (outputString[currentLetter] - 32)) | (palette<<12));

      //Next space
      x++;
   }

   //Return next open line
   return (y + 1);
}


When I pass call this function as:

Code:

currentLine = Output(8, bg_font_graphics, bg_font_palette, DIALOGUE_WINDOW_LEFT + 3, currentLine, DIALOGUE_WINDOW_RIGHT, 32, "%s", message->responses[3]);


Where message->responses[3] = "1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0"

The thing returns 53... incorrect.

Strangeness #1: If I change message->responses[3] to "1234...etc" (no spaces) it works fine.
Strangeness #2: If I check the value of y immediately prior to returning, it is 11.

!I AM SO CONFUSED!

Thanks again,
staringmonkey

#513 - Quirky - Wed Jan 08, 2003 9:26 am

Does this work then?

char outputString[(strlen(originalString) + 32)]; //String with variables

because I can't imagine it'd compile - the copiler doesn't know the size of outputString at compile time... Anyway that's by the by, when you do this:

vsprintf(outputString, originalString, arguments)

"arguments" is longer than 32, which is the extra space you've alloted in your char buffer, isn't it? That could explain why it works with "1234567890" but not "1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0". Any behaviour after this step is undefined. Have you tried setting

char outputString[200];

or something really big that will definitely hold all the chars? I'm probably way off though...

#515 - tom - Wed Jan 08, 2003 9:48 am

Quirky wrote:
Does this work then?

char outputString[(strlen(originalString) + 32)]; //String with variables


this is certainly one of the problems. the size of a variable on the stack must be a constant value, determinable at compile time. i wonder why this even compiles. vc++ refuses to compile that (which is correct behaviour)

i'd try something like that:

char *outputString = (char*)malloc(strlen(originalString)+32);

don't forget to free up the allocated memory at the end of the function.

or use a large enough string, as Quirky suggested, although that is of course not very safe =)

#516 - staringmonkey - Wed Jan 08, 2003 10:01 am

Hey,

Yep, you guys are right. I just made this discovery myself, albeit in a far more roundabout way then you guys did. (Lets just say it involved lots of futzing with how the string was passed.)

Stupid, stupid mistake... oh well... I guess sometimes you have to learn the hard way. Not that I'll look at it that way in two weeks when my first milestone is due. :)

Thanks again,
The ever-so-humbled staringmonkey

#518 - ampz - Wed Jan 08, 2003 10:23 am

Actually, an local array CAN be of variable size. This is a C99(I think) feature that GCC supports. (however, not all compilers do support it)