473,396 Members | 1,683 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Strange behavior with Standard C++ 'string' objects

Hello,

I'm new to the boards, and I've been struggling with a problem porting my
company's code from Visual C++ 6.0 to Visual C++ 2005.

We've found some crashes that I've traced to the 'c_str()' member of the
standard string class. I've debugged into the deepest layers of the system
code and cannot explain this.

What we have is a class with a private 'string' member:

string _linkType;

And public function that returns it:

class Link
....
string getLinkType() const {return _linkType; }

When attempting to access the string as a char * later in the code, the
resulting string "1M" does not get extracted properly:

Link *ilink;
const char *pLinkType;
pLinkType = ilink->getLinkType().c_str();

The result of this is that pLinkType is "".

Now - here's the weird part.

const char *blah;
string strvalue;
strvalue = ilink->getLinkType();
blah = strvalue.c_str();

If I do this, 'blah' contains the proper string '1M'.

How can this be? If I break apart the operation into two lines, it works.
Keep it as one line and it fails!?

I've tried defining the member as std::string and return value from the get
function as std::string as well, with no change in behavior. I'd really
like a good solution to this, as this example literally shows up hundreds of
times in our code. It would be a lot of work to make the massive changes to
ensure the proper value is getting returned.

This works just fine in Visual C++ 6.0. I've even installed VC++2005 SP1 to
see if it was fixed there, with no change.

Thanks so much in advance for your help!
Mar 8 '07 #1
7 1746
Brian Kunz wrote:
Hello,

I'm new to the boards, and I've been struggling with a problem
porting my company's code from Visual C++ 6.0 to Visual C++ 2005.

We've found some crashes that I've traced to the 'c_str()' member of
the standard string class. I've debugged into the deepest layers of
the system code and cannot explain this.

What we have is a class with a private 'string' member:

string _linkType;

And public function that returns it:

class Link
....
string getLinkType() const {return _linkType; }

When attempting to access the string as a char * later in the code,
the resulting string "1M" does not get extracted properly:

Link *ilink;
const char *pLinkType;
pLinkType = ilink->getLinkType().c_str();

The result of this is that pLinkType is "".
This produces a pointer into a temporary return value, which disappears at
the semi-colon.
>
Now - here's the weird part.

const char *blah;
string strvalue;
strvalue = ilink->getLinkType();
blah = strvalue.c_str();

If I do this, 'blah' contains the proper string '1M'.
Because "1M" is saved inside strvalue, and blah points to that value. blah
is valid as long at strvalue doesn't change.
>
This works just fine in Visual C++ 6.0.
No it didn't. It just seemed to work. :-)
I've even installed VC++2005
SP1 to see if it was fixed there, with no change.
That's a good idea anyway.

Bo Persson
Mar 8 '07 #2
Brian Kunz wrote:
Link *ilink;
const char *pLinkType;
pLinkType = ilink->getLinkType().c_str();

The result of this is that pLinkType is "".
What happens here is that getLinkType() returns a temporary object.
You're not storing it anywhere, so it gets destructed as soon as the
assignment is executed. c_str() is getting a pointer to a member of this
temporary string. When the string returned by getLinkType() goes out of
scope, the const char* returned by c_str() gets invalidated too.
const char *blah;
string strvalue;
strvalue = ilink->getLinkType();
blah = strvalue.c_str();

If I do this, 'blah' contains the proper string '1M'.
That works as expected, since the string returned by getLinkType is no
longer a temporary. You have a local copy of it, so blah will be valid
as long as strvalue is alive. However, as soon as strvalue goes out of
scope, the value of blah will become undefined.
How can this be? If I break apart the operation into two lines, it works.
Keep it as one line and it fails!?
It's not a matter of having 1 line or 2 lines, it has to do with the
temporary. You have to remember that unless you declare a variable and
give a name to it, it's nothing more than a temporary that dies at the
end of the instruction (when the semicolon is closed). Getting a pointer
to a temporary, or one of its members, is pretty dagerous an unpredictable.

In VC6 the compiler didn't immediately destroy your temporary, so your
pointer was still alive. However, there's no such guarantee. You were
exploiting undefined behavior, and with VC++ 2005 your luck has turned
around. In fact, you should be happy that you caught a bug, because it
was always hanging in the air, waiting for an accident to happen.

Tom
Mar 8 '07 #3
Thank you both so much for your help. What you're saying makes complete
sense. I guess that fact that it worked in 6.0 led me to believe a change in
behavior. Bottom line is, we got lucky and our luck ran out.

Thanks again!

"Tamas Demjen" wrote:
Brian Kunz wrote:
Link *ilink;
const char *pLinkType;
pLinkType = ilink->getLinkType().c_str();

The result of this is that pLinkType is "".

What happens here is that getLinkType() returns a temporary object.
You're not storing it anywhere, so it gets destructed as soon as the
assignment is executed. c_str() is getting a pointer to a member of this
temporary string. When the string returned by getLinkType() goes out of
scope, the const char* returned by c_str() gets invalidated too.
const char *blah;
string strvalue;
strvalue = ilink->getLinkType();
blah = strvalue.c_str();

If I do this, 'blah' contains the proper string '1M'.

That works as expected, since the string returned by getLinkType is no
longer a temporary. You have a local copy of it, so blah will be valid
as long as strvalue is alive. However, as soon as strvalue goes out of
scope, the value of blah will become undefined.
How can this be? If I break apart the operation into two lines, it works.
Keep it as one line and it fails!?

It's not a matter of having 1 line or 2 lines, it has to do with the
temporary. You have to remember that unless you declare a variable and
give a name to it, it's nothing more than a temporary that dies at the
end of the instruction (when the semicolon is closed). Getting a pointer
to a temporary, or one of its members, is pretty dagerous an unpredictable.

In VC6 the compiler didn't immediately destroy your temporary, so your
pointer was still alive. However, there's no such guarantee. You were
exploiting undefined behavior, and with VC++ 2005 your luck has turned
around. In fact, you should be happy that you caught a bug, because it
was always hanging in the air, waiting for an accident to happen.

Tom
Mar 8 '07 #4
In article <F0**********************************@microsoft.co m>,
=?Utf-8?B?QnJpYW4gS3Vueg==?= <Br*******@discussions.microsoft.comwrote:
>Thank you both so much for your help. What you're saying makes
complete sense. I guess that fact that it worked in 6.0 led me to
believe a change in behavior. Bottom line is, we got lucky and our
luck ran out.
I think you're going to find that 2005 is a real nitpicker when it
comes to sketchy code. I much prefer things to fail instantly and
obviously, rather than being lucky.

Nathan Mates

--
<*Nathan Mates - personal webpage http://www.visi.com/~nathan/
# Programmer at Pandemic Studios -- http://www.pandemicstudios.com/
# NOT speaking for Pandemic Studios. "Care not what the neighbors
# think. What are the facts, and to how many decimal places?" -R.A. Heinlein
Mar 8 '07 #5

"Brian Kunz" <Br*******@discussions.microsoft.comwrote in message
news:F0**********************************@microsof t.com...
Thank you both so much for your help. What you're saying makes complete
sense. I guess that fact that it worked in 6.0 led me to believe a change
in
behavior. Bottom line is, we got lucky and our luck ran out.
This is the fix you are probably looking for, that won't require a million
changes to scattered code:

class Link
....
const std::string& getLinkType() const {return _linkType; }

pLinkType = ilink->getLinkType().c_str(); // now OK
Mar 8 '07 #6


"Ben Voigt" wrote:
This is the fix you are probably looking for, that won't require a million
changes to scattered code:

class Link
....
const std::string& getLinkType() const {return _linkType; }

pLinkType = ilink->getLinkType().c_str(); // now OK
YES YES! Perfect! That works wonderfully, thank you so much.
Mar 8 '07 #7

"Brian Kunz" <Br*******@discussions.microsoft.comwrote in message
news:06**********************************@microsof t.com...
>

"Ben Voigt" wrote:
>This is the fix you are probably looking for, that won't require a
million
changes to scattered code:

class Link
....
const std::string& getLinkType() const {return _linkType; }

pLinkType = ilink->getLinkType().c_str(); // now OK
YES YES! Perfect! That works wonderfully, thank you so much.
Note that the string object is now the actual member variable, so the
lifetime is now equal to the lifetime of the object ilink refers to. That's
probably long enough for all callers, but it might not always be.
Mar 9 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

36
by: Dmitriy Iassenev | last post by:
hi, I found an interesting thing in operator behaviour in C++ : int i=1; printf("%d",i++ + i++); I think the value of the expression "i++ + i++" _must_ be 3, but all the compilers I tested...
13
by: Neil Zanella | last post by:
Hello, I wonder whether anyone has ever come across the following g++ compiler error message. I don't recall ever seeing it before. I solved my problem but I am still not sure about what this...
31
by: Bjørn Augestad | last post by:
Below is a program which converts a double to an integer in two different ways, giving me two different values for the int. The basic expression is 1.0 / (1.0 * 365.0) which should be 365, but one...
6
by: Joseph Geretz | last post by:
Writing an Outlook AddIn with C#. For the user interface within Outlook I'm adding matching pairs of Toolbar buttons and Menu items. All of the buttons and menu items are wired up to send events to...
3
by: sara | last post by:
Very strange behavior, but I suspect some is A2K and some might be for me to correct. Just trying to see if anyone can help and advise. We have a database that's been running for a few years...
1
by: Nicholas Palmer | last post by:
Hi all, Got a question about the AspCompat=true page property. First a little background. We have an ASP.NET app that uses two COM components. The first is the Microsoft OWC 11 components and...
8
by: FBM | last post by:
Hi there, I am puzzled with the behavior of my code.. I am working on a networking stuff, and debugging with eclipse (GNU gdb 6.6-debian).. The problem I am experiencing is the following: ...
160
by: DiAvOl | last post by:
Hello everyone, Please take a look at the following code: #include <stdio.h> typedef struct person { char name; int age; } Person;
20
by: Pilcrow | last post by:
This behavior seems very strange to me, but I imagine that someone will be able to 'explain' it in terms of the famous C standard. -------------------- code -----------------------------------...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.