Empty GLUI_TextBox crashes on window 7
Brought to you by:
nigels
I was using glui on Ubuntu without any problems, but when I tried the same code on my Windows 7 it crashed.
I reduced the code to a few lines and I found out that it crashed when I created an empty TextBox.
When I add a text in the TextBox (with set_text) then the program will run, but it will still crash when the text is erased afterwards.
The crash occurs in glutMainLoop and I get a the error "Debug Assertion Failed!".
The file is ...\xstring on line 1575 with the expression "string subscript out of range".
The issue seems to be that the windows implementation of std::string does slightly different range checking when getting a char at an index. On Linux, if you get the first char of an empty string it will return '\0'. On windows it just screams and dies. Running a release build doesn't crash but it does have a lot of unexpected behavior.
I too was running into this and have found the specific cause.
In VS2010, the default debug project settings define the preprocessor directive
_ITERATOR_DEBUG_LEVEL=2
This causes code inside xstring to perform range checking on calls to string::operator[], like so:
if _ITERATOR_DEBUG_LEVEL == 2
#elif _ITERATOR_DEBUG_LEVEL == 1
_SCL_SECURE_VALIDATE_RANGE(_Off < this->_Mysize);
#endif / _ITERATOR_DEBUG_LEVEL == 2 /
The variable _Mysize apparently represents string length minus null characters - i.e. the value returned by calling string::length. Therefore the range check fails and
throws an out of range exception.
Solutions:
In debug build configuration, in project properties -> C/C++ -> Preprocessor, add the following directive:
_ITERATOR_DEBUG_LEVEL=0
*note: this is probably not a good idea as the you will lose a number of iterator-related asserts across the entire project, but it is the quick and dirty way to get around the issue.
The other way is to modify a few lines of glui_edittext.cpp to check for an empty string before attempting to access the 0-indexed character object of a string.
For example, following lines starting at line 849 :
for( i=start; i<=end; i++ )
width += char_width( text[i] );
should be modified to something like:
if(!text.empty())
for( i=start; i<=end; i++ )
width += char_width( text[i] );
There are a few more places in the source that should be modified in a similar way. I can post the source with all of my changes if someone wants it.
Hope this helps someone :) Cheers!
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
Would you mind posting your glui fixes nobody :)? What other files need modified? I guess I can just keep updating the code till I find all the situations where the error arises.
I am not a dev of the project, but wouldn't mind to help since I find that some things could be factored back in so I don't revisit them. Apologies for the bad formatting, I have no idea how to do it right. Attached file is nicer.
/***** GLUI_EditText::substring_width() **/
int GLUI_EditText::substring_width( int start, int end )
{
int i, width;
width = 0;
// JOHN: empty text
if (start == end)
return 0;
for( i=start; i<=end; i++ )
width += char_width( text[i] );
return width;
}
/***** GLUI_EditText::update_substring_bounds() **/
int GLUI_EditText::update_substring_bounds( void )
{
int box_width;
int text_len = (int)text.length();
int old_start, old_end;
old_start = substring_start;
old_end = substring_end;
/ Calculate the width of the usable area of the edit box /
box_width = MAX( this->w - this->text_x_offset
- 4 / 2 * the two-line box border /
- 2 * GLUI_EDITTEXT_BOXINNERMARGINX, 0 );
CLAMP( substring_end, 0, MAX(text_len-1,0) );
CLAMP( substring_start, 0, MAX(text_len-1,0) );
// JOHN: avoid checks for empty text
if (text_len == 0) {
return false; / bounds did not change /
}
/****** GLUI_EditText::draw_text() ***/
void GLUI_EditText::draw_text( int x, int y )
{
GLUI_DRAWINGSENTINAL_IDIOM
int text_x, i, sel_lo, sel_hi;
// JOHN: empty text
if (text.size() == 0)
return;
/***** GLUI_EditText::draw_insertion_pt() **/
void GLUI_EditText::draw_insertion_pt( void )
{
int curr_x, i;
if ( NOT can_draw() )
return;
/ Don't draw insertion pt if control is disabled /
if ( NOT enabled )
return;
if ( debug ) dump( stdout, "-> DRAW_INS_PT" );
if ( sel_start != sel_end OR insertion_pt < 0 ) {
return; / Don't draw insertion point if there is a current selection /
}
/ printf( "insertion pt: %d\n", insertion_pt ); /
curr_x = this->x_abs + text_x_offset
+ substring_width( substring_start, substring_end )
+ 2 / The edittext box has a 2-pixel margin /
+ GLUI_EDITTEXT_BOXINNERMARGINX; / plus this many pixels blank space
between the text and the box /
// JOHN: avoid repeat on zero char
if (text.size() > 0)
for( i=substring_end; i>=insertion_pt; i-- ) {
curr_x -= char_width( text[i] );
}
Correction to the above. fixes: 1) Insert position was out of place and 2) no text caused greyed field