tags:

views:

102

answers:

2

Where does the pointer returned by calling string::c_str() point to ? In the following code snippet, I thought I will give get a segmentation fault but it gives me the correct output. If the pointer returned by string::c_str() points to an internal location inside the string object, then when the function returns and the object destructor gets invoked, I should get an invalid memory access.

#include <iostream>
#include <string>
using namespace std;

const char* func()
{
    string str("test");
    return str.c_str();
}

int main()
{
    const char* p = func();
    cout << p << endl;
    return 0;
}

Output: test
Compiler: g++ 4.3.3
Platform: ubuntu 2.6.28-19
+8  A: 

Where does the pointer returned by calling string::c_str() point to?

It points to some place in memory where a null-terminated string containing the contents of the std::string is located.

The pointer is only valid until the std::string is modified or destroyed. It is also potentially invalidated if you call c_str() or data() again.

Basically, your safest bet is to assume the pointer obtained from c_str() is invalidated the next time you do something to the std::string object.

I should get an invalid memory access.

No, you get undefined behavior. You might get a memory access error of some kind (like a segmentation fault), but your program also might appear to continue running correctly. It might appear to work one time you run your program but fail the next.

James McNellis
AFAICT, the pointer returned by `c_str()` is valid until the next call to a non-const function. Since `c_str()` and `data()` are both `const` themelves, they may not invalidate previously returned pointers.
MSalters
@MSalters: I thought so as well, but: "References, pointers, and iterators referring to the elements of a `basic_string` sequence may be invalidated by the following uses of that `basic_string` object: ... Calling `data()` and `c_str()` member functions" (C++03 21.3/5). I would consider `c_str()` as returning a pointer to an element in the string so that pointer _could_ be invalidated by another call to `c_str()`. I could be wrong on that.
James McNellis
I think the idea there was that basic_string might implement c_str() by appending a `\0` to its internal buffer, and returning a pointer to that appended buffer. Such an implementation would rarely store a `\0`, and never store two copies. The text you quote allows this - it's unspecified whether `c_str` returns a pointer to the elements or a pointer to a copy of those elements.
MSalters
+1  A: 

What would you expect this to print out?

#include <iostream>
#include <string>

int main()
{
  int* test = new int[20];
  test[15] = 5;
  std::cout << test[15] << "\n";
  delete[] test;
  std::cout << test[15] << "\n";
  return 0;
}

In release mode on VS 2010, I get this result:

5
5

Deallocated memory doesn't necessarily throw an exception when you try to access it. The value doesn't necessarily get re-written, either. (Interestingly enough, if I change the compile to debug mode, the compiler overwrites the value with -572662307).

What happens when you try to access it is undefined by the standard. That means the compiler can do whatever it feels like doing, or choose to do nothing. (Or crash your program, or blow up the universe...)

Merlyn Morgan-Graham
Excellent illustration ....
Tanuj