PDA

View Full Version : Stop the madness



azcoder
01-23-2006, 12:48 PM
I have an application that runs on Windows, Linux, and mac. I recently attempted to run it on a laptop running XP and I get an Access Violation during a glCallLists call. I am also switching to VS 2005.

I have boiled it down to a problem using std:string and glCallLists.

This works:
glCallLists( 26, GL_BYTE, "This is simply too strange");

This causes a violation:
std::string s="This is simply too strange";
glCallLists( 26, GL_BYTE, s.c_str());


Any advice/tips greatly appreciated...
Is it the MS STL implementation - should I try STL Port? Or is it more likely a driver issue? (Card in question is an nvidia 7800 Go).

Thanks in advance for any help
Bob

azcoder
01-23-2006, 12:54 PM
This also works:

char str[]="This is simply too strange";
glCallLists( 26, GL_BYTE, str);

I guess std::string.c_str() does not work?

dorbie
01-23-2006, 01:13 PM
No real idea, when/where does the violation occur?

If it's later than the call itself it *may* be something going out of scope and the graphics call getting buffered by the driver.

Try a glFlush() right after the glCallLists call, but it's a shot in the dark.

rgpc
01-23-2006, 04:19 PM
From the MSDN reference on the c_str function:


The pointer value is not valid after calling a non-const function, including the destructor, in the basic_string class on the object.Personally I don't really understand what they are trying to say, but it might be that the pointer you are using is invalid by the time glCallLists gets around to using it.

Try copying the string into an array and using the array and see if that works.

Korval
01-23-2006, 04:48 PM
To be a bit more explicit about the problem, it works like this.

All glCallLists does is note the fact that you want to call the list whose string you gave. At some later time, it is going to asyncronously actually do the list calling.

When you store the constant string into the 'char str[]' array, all it is doing is storing a pointer to the string. This string is compiled into your executable, and will therefore always be available while your application is running. No problem.

When you use a std::string, new memory (belonging to std::string) is allocated on the heap and the constant string is copied into it. When the std::string goes off the stack, this memory is deallocated, thus invalidating the pointer returned by std::string::c_str(). When the list calling happens, the pointer that it was given is no longer valid.

This is why std::string::c_str() is dangerous.

tamlin
01-23-2006, 07:03 PM
Sorry for going so much OT, but there were some very serious errors here I felt couldn't go uncommented.


Originally posted by Korval:
When you store the constant string into the 'char str[]' array, all it is doing is storing a pointer to the string.This is incorrect.

The way OP displayed the code, the compiler will allocate space for the char array on the stack, then initialize that space with the actual string literal. The declaration of an array never store just a pointer to the contents - it stores the actual contents.

This string is compiled into your executable, and will therefore always be available while your application is running. No problem.

This is also false. The character array, as displayed, is only valid within that (and nested) stack frame(s).

When you use a std::string, new memory (belonging to std::string) is allocated on the heap and the constant string is copied into it.

While that is a valid interpretation (and is true for this case), I just want to raise a warning that this is not universally true. For VC 7 (or was it 7.1?) Microsoft changed basic_string implementation, so if you have a string less than 16 char's it's stored inside the very basic_string object, meaning it would also be placed on the stack and no heap operations whatsoever would be required or used.

This is why std::string::c_str() is dangerous.

Sometimes the keyboard is more dangerous than a sword. :)

A few suggestions to OP though:

- Have you tried making the string smaller than 16 chars, to see if that also crashes?

- Have you tried storing the returned result from c_str() in a plain const char* and trace it (e.g. printf or OutputDebugString)?

sqrt[-1]
01-24-2006, 01:28 AM
ack! Korval -so much disinformation in one post!

As to the problem at hand, perhaps you are doing something bad with memory and the STL string points to bad memory itself?

Can you post an example app that has this problem?
Also, does this app use multiple threads?

Finally to toot my own horn, have you tried running GLIntercept (http://glintercept.nutty.org/index.html) on it with with the "Full Debug" profile?

knackered
01-24-2006, 05:17 AM
I believe the word is 'misinformation'.
Personally, I'm glad to see that Korval is only human, after all. The icing on the cake would be an admission, not a side-step, just an admission that he got it wrong - and maybe a little joke about working too hard.

azcoder
01-24-2006, 07:19 AM
Well I resolved my problem...and it was my own error (of course).

I had built a text rendering class to display text on the screen. This class allocated an instance of a trivial DisplayText class that consisted only of a std::string and x,y coordinates. This instance was pushed into an stl queue that was later popped and rendered during the render stage. After popping it off the queue and rendering it I had forgotten to delete the instance.

The curious thing is that I can understand that this would leak memory and eventually crash the app - but I'm still not sure why this caused immediate access violations(and only whne porting to the latest VS2005).

Thanks again for all your replies - it definitely helped me out in thinking about the problem.

Korval
01-24-2006, 09:23 AM
The way OP displayed the code, the compiler will allocate space for the char array on the stack, then initialize that space with the actual string literal. The declaration of an array never store just a pointer to the contents - it stores the actual contents.Really? Hmm. Maybe that's why I tend to use pointer syntax.