const char* not crashing?

Started by
22 comments, last by Sneftel 14 years, 10 months ago
Why doesn't the following code crash?
#include <string>
#include <iostream>

const char* test()
{
  std::string s = "hallo";
  s += "!!";
  return s.c_str();
}

int main()
{
  const char* c = test();
  
  std::cout << c;
 
  std::cin.get(); 
}

At the end of test(), the std::string gets deleted. How is the memory handled so that the const char* keeps pointing to something valid, and when is that deleted? The string isn't one simple constant but two added ones, so it can't just point to the literal strings in the code.
Advertisement
Quote:Original post by Lode
Why doesn't the following code crash?

*** Source Snippet Removed ***

At the end of test(), the std::string gets deleted. How is the memory handled so that the const char* keeps pointing to something valid, and when is that deleted?

The string isn't one simple constant but two added ones, so it can't just point to the literal strings in the code.
That's undefined behaviour. I'd guess that the only reason it works is that either the memory occupied by the string data isn't filled with gibberish when it's freed (I.e. not using the debug CRT), or your STL implementation keeps small strings on the stack, and the stack isn't being reset with gibberish when the function ends.
Quote:Original post by Lode
Why doesn't the following code crash?

At the end of test(), the std::string gets deleted. How is the memory handled so that the const char* keeps pointing to something valid, and when is that deleted?

The string isn't one simple constant but two added ones, so it can't just point to the literal strings in the code.
std::string.c_str() typically returns a pointer to the string's internal buffer, and even though that buffer will have been freed, the memory won't have been overwritten yet. Given that it is a small string, and it has only just been freed, you probably won't trigger the operating system's memory protection features when you access that memory.

Obviously, you should never do this, and should return the std::string itself instead.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Well it's for a C-style dll interface, I need to return it as a const char* :(

And appearantly other people have also been doing it with code like that what I posted, which is what made me wonder about it and post it here in the first place.

What were the developers of C smoking when they decided not to add useful strings to the language and do they realise what they have caused still 30 years later?
Quote:Original post by Lode
What were the developers of C smoking when they decided not to add useful strings to the language

They didn't smoke anything. They just thought "Hey, let's create a portable assembly language!".
Quote:Original post by Lode
Well it's for a C-style dll interface, I need to return it as a const char* :(


There's no really good solution for this. The best thing you can do is have the caller give you some buffer where you'll deposit the result. Make sure the caller also specifies the size of the buffer, so you know when to stop if the string is too long.

Alternatively, you can return a pointer to a malloc()ed block of memory that they can release using free(). In this case, document this fact as loudly as you can, because someone will make a memory leak out of it.

For completeness, you could also return a pointer to some global buffer (similar to making s static in your example. However, this has its own problems.
Quote:Original post by Lode
What were the developers of C smoking when they decided not to add useful strings to the language and do they realise what they have caused still 30 years later?

What were the developers of FORTRAN smoking? What were the developers of APL smoking? Who smoked so much to actually invent any 2nd generation programming language?

And what were you smoking when you decided to use C where C++ was intended?

Don't take serious, just a small, benevolent side blow, not sure what I smoked to write such BS ;)


C was always about being minimalistic and close to the metal, DevFred's phrase about C being a "portable assembly language" is not fetched from to far away.

Also, C was always for people "who know what they do", i.e. when the return a pointer-to-char then they know why and what will happen. Pretty much like when you are logged in as root on a Unix box, C shows no mercy for programmer-fail. That analogy was no accident, btw.

One last note: C really does not have strings, it only has array of char. And a bit of syntactic sugar to make initialization a bit more comfortable:

#include <stdio.h>int main () {        char mem[] = {'h','e','l','l','o',',',' ','w','o','r','l','d','\0'};        char *str = mem;        ...        puts (str);}
Quote:Original post by Lode
What were the developers of C smoking when they decided not to add useful strings to the language and do they realise what they have caused still 30 years later?


C is a glorified PDP-11 assembler -- the creators, Kerninghan and Ritchie, didn't think: they just wanted to get UNIX done.
Quote:Original post by Lode
What were the developers of C smoking when they decided not to add useful strings to the language and do they realise what they have caused still 30 years later?

I think it's more like "hey, we need some way to handle text in our new language. I have an idea on how we can do so much better than FORTRAN's Hollerith variables....".

Just evaluate their design decisions in the context of what was available in the 1960s.

Stephen M. Webb
Professional Free Software Developer

Quote:Original post by Bregma
Quote:Original post by Lode
What were the developers of C smoking when they decided not to add useful strings to the language and do they realise what they have caused still 30 years later?

I think it's more like "hey, we need some way to handle text in our new language. I have an idea on how we can do so much better than FORTRAN's Hollerith variables....".

Just evaluate their design decisions in the context of what was available in the 1960s.


Upon first glimpse, those Hollerith variables look like labeled data sections in some assembler. Would that assumption be correct?

This topic is closed to new replies.

Advertisement