0

In a C++ program, where is constant data stored, especially string constants ?

I am asking because in the following question:

Why can creating a static const std::string cause an exception?

The answer by Damon, has the following at the end:

A string_view will, contrary to a string, not allocate non-constant memory, copy constant data into that, and then pretend it's constant. Instead, it will manage a pointer directly to the constant data, and that's all.

That way, your constants are truly (not just formally) constant, there are no allocations, no possibility of exceptions, and no double memory usage. And for the most part, it still looks and smells like a string. The only notable differences being that a string_view doesn't guarantee nul-termination (but the character constant it points to does, so this is irrelevant), and the fact that it's really constant, not modifiable... which is exactly what you want.

Dont even the constants need to be stored in memory some where ? And if they are stored in memory (since memory is finite), isn't it possible an exception can be thrown because there is no more memory ?

Community
  • 1
  • 1
Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190
  • 2
    The memory for them is loaded before any code runs. So no runtime exception is possible. If you can run, then the memory is already there. – Raymond Chen Nov 04 '16 at 04:53
  • 1
    related http://stackoverflow.com/questions/349025/is-a-string-literal-in-c-created-in-static-memory also https://isocpp.org/wiki/faq/ctors#static-init-order – Paul Rooney Nov 04 '16 at 05:01

2 Answers2

2

The problem is that a std::string is an object, not just plain data.

This means that when you declare

static const std::string foobar = "foobar";

the static data that is reserved in the binary is the one for the literal "foobar" (intended as a const char*) and the space required to store a std::string object, which is NOT the space required to store its contents.

Imagine a std::string as something like, let's say

class string {
private:
  size_t length;
  char* data;

public:
  string(const char* data) : length(strlen(data), data(new char[length+1]) {
    strcpy(this->data, data);
  }
  ~string() { delete data; }
};

This is a trivial unsafe piece of code but it's just to give you the idea. When you have your static std::string the only space required is sizeof(char*)+sizeof(size_t) bytes, since the data itself is dynamically allocated on heap.

That's why using a static const std::string wastes twice the space: for the literal itself, which is passed to the constructor of the string, and for the std::string.

Now this object is not "pre-constructed" at compile time. It's constructed at runtime and the standard doesn't guarantee you when this happens exactly (indeed if it happens before calling main you are not able to catch any exception that the constructor may throw).

The cited string_view is a wrapper around a const char* which doens't waste memory as it stores only a pointer to the contents, which is not the case for a normal std::string which is designed to be mutable.

Community
  • 1
  • 1
Jack
  • 131,802
  • 30
  • 241
  • 343
2

Static constants are stored in the 'data' segment of the executable. Exactly where they are stored may vary from system to system, but in the case of Linux for example they are loaded as part of the executable and appear immediately above the 'text segment' in the process memory map.

They are loaded into the process memory map by the operating system before the program starts executing; therefore if there is not enough memory for them, the program cannot even load, much less throw an exception!

If you are interested in the memory layout of processes, I found this blog post to be most helpful.

harmic
  • 28,606
  • 5
  • 67
  • 91