![]() |
| | #1 |
| Math wizard Join Date: Dec 2006 Location: Minot, ND, USA
Posts: 516
| Unexplained "unhandled exception" Code: void DrawBMPFont(char Text[1024], short StartX, short StartY, short width, int XBorder, int YBorder)
{
... // notes and local variables
if (Text[1023] != 0) // if last possible character is not null
{
Text[1023] = 0; // the null character must be enforced.
}
... // the rest of the function
}
int sample[12]; I can use sample[11] just fine but not sample[12]. Why is it giving the "unhandled exception" notice here? The array is 1024 long and the one accessed is within the range at 1023. If it was 1024, I can understand that, but this is 1023.... If I comment the if statement out, another strange problem occurs. Code: while ((Text[ArrayIndex] != TextSpace) || (Text[ArrayIndex] != 0x0A) || (Text[ArrayIndex] != 0)) // loop until a space or line feed is encountered
{
PosX += Font.CharWidth[Text[ArrayIndex]]; // add the character's width
ArrayIndex++;
LoopCount[0]++; // debugging only
if (LoopCount[0] >= 10000000) // ten million loops is way too many
{
sprintf(DebugDetails, "Warning: an infinite loop in the first loop is present!"); // for debugging
MessageBox(hwnd, DebugDetails, "Debug Results", MB_OK);
break; // terminate the function regardless of the function's success
}
}
if (LoopCount[0] >= 10000000)
{
break; // break the main loop
}
|
| ulillillia is offline | |
| | #2 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,381
| |
| brewbuck is offline | |
| | #3 |
| and the hat of vanishing Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,214
| We need more code, ideally something small which is complete. Say Code: int main ( ) {
DrawBMPFont("Samplestring", 0, 0, 0, 0, 0);
return 0;
}
__________________ If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut. Up to 8Mb PlusNet broadband from only £5.99 a month! |
| Salem is offline | |
| | #4 |
| Math wizard Join Date: Dec 2006 Location: Minot, ND, USA
Posts: 516
| Seems like I need to post the full function, again. Code: void DrawBMPFont(char Text[1024], short StartX, short StartY, short width, int XBorder, int YBorder)
{
/* This function draws bitmap font text to the screen.
Rules:
* The last character's numerical value must be zero. If it's not zero, it should be set prior to processing to prevent infinite loops.
* Wordwrap occurs only when the space character is encountered.
* Wordwrap should never occur when a "\n" is encountered. Instead, the row should advance and the x position reset.
* Strings are processed until a space is encountered. When encountered, wordwrap is checked.
* If there's enough space, the word is placed on the next line. If not, text wraps to the next line below.
* The X and Y parameters set the position of the upper left corner where text is to be drawn to.
* The width parameter specifies how wide of an area to cover before wordwrap is used.
* The border parameters are used to set padding for easier use and reading
* Processing should continue until the null character is found, from which it stops.
*/
short PosX = 0; // initialize start positions
short PosY = 0;
short VSpacing = (short)FontInfo.biHeight; // the vertical spacing
unsigned short ArrayIndex = 0; // text array position
unsigned short StartArrayIndex; // first character of the current word
unsigned short EndArrayIndex; // first character of the next word
int DrawXPosition = 0;
int DrawYPosition = 0;
int SourceXWidth = 2;
int DrawXWidth = 2;
int SourceXPosition = 0;
int LoopCount[3] = {0, 0, 0}; // debugging only
width = width + 2 - XBorder*2; // gives the actual width. +2 for the spacing between characters XBorder*2 because there are two sides
SelectObject(HDCBitmap, FontBMPHandle);
/*
if (Text[1023] != 0) // if last possible character is not null
{
Text[1023] = 0; // the null character must be enforced. // Unhandled exception - Huh!?
}
*/
while (Text[ArrayIndex] != 0) // loop until the null character is reached
{
StartArrayIndex = ArrayIndex; // copy the starting point in the string
while ((Text[ArrayIndex] != TextSpace) || (Text[ArrayIndex] != 0x0A) || (Text[ArrayIndex] != 0)) // loop until a space, line feed, or the null character is encountered // an infinite loop, but how?
{
PosX += Font.CharWidth[Text[ArrayIndex]]; // add the character's width
ArrayIndex++;
LoopCount[0]++; // debugging only
if (LoopCount[0] >= 10000000) // ten million loops is way too many
{
sprintf(DebugDetails, "Warning: an infinite loop in the first loop is present!"); // for debugging
MessageBox(hwnd, DebugDetails, "Debug Results", MB_OK);
break; // terminate the function regardless of the function's success // doesn't seem to execute
}
}
if (LoopCount[0] >= 10000000) // to break the main loop
{
break; // break the main loop // doesn't execute either
}
EndArrayIndex = ArrayIndex; // copies the current array position to mark the end of a word
if (PosX > width) // if too long to display in the given width
{
PosY += VSpacing; // go down a row
PosX = 0; // and return to the leftmost position
}
else // if space remains
{
if (Text[ArrayIndex] != 0x0A) // if a linefeed is not used
{
PosX += Font.CharWidth[Text[ArrayIndex]]; // include the space character
}
}
if (Text[ArrayIndex] == 0x0A) // the linefeed
{
PosY += VSpacing; // go down a row
PosX = 0; // and return to the leftmost position
}
ArrayIndex = StartArrayIndex; // reset the array index to where the word started at, now for drawing
DrawYPosition = (int)StartY+(int)PosY+YBorder; // the Y position to draw to doesn't change
while (ArrayIndex < EndArrayIndex) // repeat until the end of the word is reached
{
DrawXPosition = (int)StartX+(int)PosX+XBorder; // this one is dynamic and sets the X position to draw to
DrawXWidth = (int)Font.CharEndPos[Text[ArrayIndex]]-(int)Font.CharEndPos[Text[ArrayIndex-1]]; // set the width of the area to draw to
SourceXPosition = (int)Font.CharEndPos[Text[ArrayIndex-1]]; // the start drawing point is the ending point of previous character
AlphaBlend(HDCBack, DrawXPosition, DrawYPosition, DrawXWidth, FontInfo.biHeight, HDCBitmap, SourceXPosition, 0, DrawXWidth, FontInfo.biHeight, AlphaUsage); // draw the anti-aliased character
PosX += Font.CharWidth[Text[ArrayIndex]]; // add the character's width
ArrayIndex++;
LoopCount[1]++;
if (LoopCount[1] >= 10000000) // ten million loops is way too many
{
sprintf(DebugDetails, "Warning: an infinite loop in the second loop is present!"); // for debugging
MessageBox(hwnd, DebugDetails, "Debug Results", MB_OK);
break; // terminate the function regardless of the function's success
}
}
if (LoopCount[1] >= 10000000)
{
break; // break the main loop
}
if (Text[ArrayIndex] == 0) // the null character is encountered
{
break; // terminate the loop
}
LoopCount[2]++;
if (LoopCount[2] >= 10000000) // ten million loops is way too many
{
sprintf(DebugDetails, "Warning: an infinite loop in the main loop is present!"); // for debugging
MessageBox(hwnd, DebugDetails, "Debug Results", MB_OK);
break; // terminate the function regardless of the function's success
}
}
}
// this function is used in this function:
void DrawScenery()
{
... // the rest of the scenery
DrawBMPFont("SampleString", 640, 0, 160, 1, 1); // string to display, x and y positions to draw to, the width for wordwrap, and x and y borders for "padding"
... // swapping the front and back buffers
}
Code: struct FontBase
{
short CharWidth[128];
short CharEndPos[128];
short CharHeight;
};
unsigned char FontData[70400]; // The mountains background
LPVOID FontDataPointer;
BITMAPINFO FontMainInfo;
BITMAPINFOHEADER FontInfo;
LPBITMAPINFOHEADER FontInfoPointer;
HBITMAP FontBMPHandle;
struct FontBase Font;
void FillFontStructure(unsigned short Character, unsigned short width, unsigned short ArrayIndex)
{
Font.CharWidth[Character] = width;
Font.CharEndPos[ArrayIndex] = Font.CharEndPos[Character-1] + width;
}
void SetUpFont()
{
unsigned short ArrayIndex = 0;
Font.CharHeight = FontInfo.biHeight;
Font.CharEndPos[0x1F] = 0; // initialize end position of a character before the space, for usage in the text drawing function
FillFontStructure(TextSpace, 4, ArrayIndex);
FillFontStructure(TextExclamation, 4, ArrayIndex);
FillFontStructure(TextQuote, 8, ArrayIndex);
FillFontStructure(TextNumber, 12, ArrayIndex);
FillFontStructure(TextDollarSign, 10, ArrayIndex);
FillFontStructure(TextPercent, 12, ArrayIndex);
FillFontStructure(TextAmpersand, 11, ArrayIndex);
FillFontStructure(TextApostrophe, 4, ArrayIndex);
FillFontStructure(TextLeftParenthesis, 6, ArrayIndex);
FillFontStructure(TextRightParenthesis, 6, ArrayIndex);
... // and so on, for each of the ASCII characters
}
Last edited by ulillillia; 04-19-2007 at 08:40 AM. Reason: First code tag left out |
| ulillillia is offline | |
| | #5 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,381
| The problem is that setting Text[1023] is a completely bogus operation. The data you passed it is just a string (a LITERAL, by the way, which means you couldn't modify any of it anyway), which is nowhere near 1024 characters long. So accessing Text[1023] is illegal. Just because you've declared the parameter as Text[1024] doesn't mean it somehow gets magically morphed into a 1024-byte object when it gets passed. |
| brewbuck is offline | |
| | #6 |
| and the hat of vanishing Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,214
| > Font.CharWidth[Character] = width; > Font.CharEndPos[ArrayIndex] = Font.CharEndPos[Character-1] + width; Why isn't this Character, to match the other array index? > if (Text[1023] != 0) Given that you're calling the function with a string constant, then a) there is no [1023] element of that string b) trying to write zero into it "just in case" will at best just trash some memory, somewhere in the middle, corrupt your code and at worst just result in an immediate segfault. All I can suggest is you step through the code one line at a time with the debugger, and put ArrayIndex into a watch window, and see what happens. I notice that you have nested while loops on the same condition. Are you sure you're not just skipping the \0 because of some faulty index arithmetic (like incrementing when already at the \0 position?)
__________________ If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut. Up to 8Mb PlusNet broadband from only £5.99 a month! |
| Salem is offline | |
| | #7 |
| Math wizard Join Date: Dec 2006 Location: Minot, ND, USA
Posts: 516
| Well, I didn't know it would be otherwise unlimited as it seems to go out to 10 million without it. The string I'm passing to the function has just 12 characters with a thirteenth one being the null character. Using my DebugTest variable (the only way I know how to debug), I see that the result of Text[12] is indeed 0. The result of Text[11], before this, is 103 which corresponds to the lowercase "g" and exactly as expected. Text[10] shows 110 as the value, the lowercase "n". For the string "SampleString", it's exactly expected. I think I may have found the cause and it's a common mistake I made when using my previous tool. Look at the condition of the first nested while loop carefully. while ((Text[ArrayIndex] != TextSpace) || (Text[ArrayIndex] != 0x0A) || (Text[ArrayIndex] != 0)) I'm encountering the null character which makes the third part false. But, since the null character is not a space nor a linefeed, the other two conditions are true. Since "OR" is used, and that at least one of the statements is true, the loop would just continue on forever no matter if spaces or linefeeds are encountered. It's a common mistake I make. For if statements, "OR" would indeed be used, but for loops, it should be the opposite intention for if's, meaning that "AND" would be used. I don't know how to get the debugger to step through code one line at a time. I pretty much don't know how to use it (Visual C++ 2005 Express). The DebugTest things I mention here and there are the only way I know of of checking values. Once I get text displayed on the screen, it'll be much easier to monitor variables without even needing the debugger, good for those beta testing things. |
| ulillillia is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Sleep() causing unexplained reduction in cpu load | sajanphilip | C++ Programming | 4 | 02-26-2008 02:58 AM |
| Unexplained Segfault | crepincdotcom | C Programming | 6 | 08-24-2006 04:19 PM |
| An "throwing exception" issue | viniciusMarques | Windows Programming | 3 | 06-02-2004 10:38 AM |
| "Microsoft C++ exception"?!? | SMurf | Windows Programming | 1 | 02-02-2002 04:24 PM |