Sign in to follow this  
Ferneu

MS Visual C++ 6.0 bug! ... or is it?

Recommended Posts

I was playing around with my home made refcounted, COW, string class. As you guys will be able to see on the code, it uses a proxy class to enable the correct behavior when overloading the [] operator. My problem is that, if I compile the code with the default VC++ 6.0 "debug" settings, it'll run just fine, but if I uses the "release" settings, where optimizations like /O2 or /O1 will be enabled (speed or size), the code fails. It seems that the compiler detects that a variable isn't needed, and just skips it, like in: Cstring s = "Hey"; char c = s[0]; printf("%c", c); It's like as if the compiler just tries to get what s[0] will return and replaces it right where it's needed, without using the stack variable I've created. What I'm thinking is that, (I AM NOT SURE OF THAT) perhaps the cast to char makes the correct overloaded operator been called, and when it skips it, it might consider s[0] as an array access and screw things up. I'm not 100% sure of that, since I've placed some debug printf() inside the overloaded operator body and they seem to be correctly called. The bottom line is: I DON'T KNOW. PLEASE HELP ME PS: I would like to see if this error persists on other compilers. I don't have access to any other than MSVC++ 6.0 Enterprise Edition (stock, no service packs applied). PS2: please don't post anything like "you should use std::string" or "you should use boost::*". Post things like "you code is wrong, idiot" or "it worked fine on GCC++" You can download the code here (the test code is small, but the string class might be kind of big to post here. But if you guys wishj to, I'll post it): http://rapidshare.de/files/14850379/vc6bug.zip.html

Share this post


Link to post
Share on other sites
The code fails, how ?

Keep in mind that you cannot pass any kind of object to printf (if the compiler optimises the char variable away).

Have you tried an explicit cast to char in the printf call ?

Have you applied all the VC6 service packs (SP6 is the last one)?

Have you tried another compiler to compare their behavior ?

Share this post


Link to post
Share on other sites
The answer to all your questions are inside my first post.
They are eighter on the post it self or they are on the test
code I've posted (well... linked to :))

Perhaps only the first one wasn't acctually ansered. Mostly because
I would like anyone out there with access to another compiler to
test it out... Anyway, the code fails with the overloaded []
operator returning incorrect values.

I'm aware of the printf() issues, as I've stated on the test
code. As a moderattor, do you think I should post the whole code
here or let it as it is now, just a link to the files? They are kind of
small, only the string class is big, with 600+ lines.

Share this post


Link to post
Share on other sites
Quote:
operator char (){ _sowner->get_char(_index); }

try:
operator char (){ return _sowner->get_char(_index); }

Also, I hope this is for learning purposes only. I don't have time to go into details but it's neither particularly well coded from a C++ point of view (#defines, old c-style headers etc.) nor particularly efficient (lots of redundant operations). If it's just for learning then fine. If it's for real use I strongly urge you to either reconsider the design or reconsider your alternatives.

You should also note that COW has been dropping out of favour as an optimisation due to poor performance when made thread-safe.

Σnigma

Share this post


Link to post
Share on other sites
So I feel like upping my karma....
I'm compiling with VS 7.1.
First off, you code shouldn't have compiled for you. You overloaded the (char) typecast operator and didn't return a value in its function body.

Up your warnings to level 4 in the project properties. Let me get back to your code and see what I come up with.

Share this post


Link to post
Share on other sites
Seems to work fine for me.

My output was:

strbug[ 0] == H
strbug[ 1] == e
strbug[ 2] == l
strbug[ 3] == l
strbug[ 4] == 0
coma found
<and then when i hit a button>
<it finishes by spelling out ", I am an optimized bug">
Press any key...

<seems to work fine in debug and release for me>
what exactly is your problem?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Perfect example why people should use std::string. Here we have a programmer trying to yet again reinvent that shouldn't be reinvented. When his implementation fails he blames everyone including the compiler but himself. Seems like the only people interested in reinventing this basic stuff are those who can't write it correctly in the first place. The ones that can are happy using stl or CString.

Share this post


Link to post
Share on other sites
blaze02: The error was the operator char(). Without a return statement he was getting whatever happened to be on the stack as his character. Under debug mode this happened to be the return value from the previously called function - _sowner->get_char(_index); - which, naturally, was giving him the "right" results. Under a release build that function call was likely being inlined and, being unused, optimised out entirely (hence the "local variable c used without having been initialized" referenced in the comments above his main function). This meant that the value on the stack where the return value was expected to be or the register where the return value was expected to be placed was not written.

AP: I think that was uncalled for. He didn't "blame everyone including the compiler but himself". He stated several times that he didn't know what was wrong. In his code one of his comments is "Probably it's just a failure inside my Cstring class (feel free to point it out to me <g>), but I could not find the problem at all.". He tried to debug it, was unable to, looked around for an explanation and found a possibility and came looking for confirmation. Nothing wrong with that. That said, if he is reinventing the wheel and not just doing this for learning purposes or because he really does need a string implementation which is guaranteed to use COW then yes, he's being silly.

Σnigma

Share this post


Link to post
Share on other sites
ha! Thanks very much Enigma and Blaze!!!!

Blaze, my problem was that it never found
the ',' on the release build, because the []
operator was returning incorrect results. Altough
it would work fine on the debug build... BUT, as you
guyes stated: There was a return missing on the proxy class.

The really weird part is that, even before Blaze sugested,
I was on the highest warning level (level 4) and it reported
nothing (nothing except the local var used without being
initialized, but it also reports that on level 3)
It had never complaint about the missing return statement.

Enigma: while developing the class I've became pretty
much aware about the thread safety issues, but as you've
guessed by the noobish code level, YES it's for learning purposes
only.

Thx fellas


PS: since some weeks ago I've been experiencing several
error on gamedev.net, several slowdowns and not being
able to post due it (hence the delay between my answers).
Am I the only one?

Share this post


Link to post
Share on other sites
Quote:
Original post by vovansim
Now that the main issue is resolved... I've been meaning to ask a stupid question. :) What's COW?

Thanks

Vovan

Copy-on-write. Basically, it delays actual copying until it is neccessary to do so:

void noCOW()
{
string one = "1234";
string two = one; //"1234" copied into two here
cout << one << two << endl;
one += "5"; //nothing changes, "5" is just tacted onto one.
cout << one << two << endl;
}

COW()
{
string one = "1234";
string two = one; //a shallow copy of one is made here
cout << one << two << endl;
one += "5"; //before this is done, a deep copy of one is made and given to two
cout << one << two << endl;
}

In the above examples, if you remove the 'one += "5"' line, you really only have one string. So with COW, you avoid that deep copy that ultimately proves unneccessary.

CM

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this