0
#include <iostream> #include <string> static uint32_t s_AllocCount = 0; // Overload of new operator. void* operator new(size_t size) { s_AllocCount++; std::cout << "Allocating " << size << " bytes\n"; return malloc(size); } void PrintName(const std::string& name) { std::cout << name << " - " << name.length() << " characters." << std::endl; } int main() { std::string name = "123456789012345"; PrintName(name); std::cout << s_AllocCount << " allocations" << std::endl; std::cin.get(); } 

The above code is a slightly modified version of that in How to make your STRINGS FASTER in C++!.

I am puzzled about the various outputs from this program in Visual Studio 2019 compiled in x86 debug.

When std::string name = "123456789012345"; the following results:

enter image description here

I understand that 8 bytes are being allocated for the pointer address. What I don't understand is that there are 15 bytes in this string. Does not the pointer address point to an 8 byte block of memory, i.e., one which can hold 8 characters?

When std::string name = "1234567890123456";, i.e., lengthened by 1 character to 16, the result is:

enter image description here

Now, an additional 32 bytes of memory have been allocated, clearly enough to hold 16 characters.

Do I understand correctly:

  1. That in the first case only 8 bytes of heap memory are being allocated for storing the string's pointer address and that the 15 characters of the string are stored on the stack?

  2. In the second case that 40 bytes of heap memory are being allocated and that both the string's pointer address and the string characters are all stored on the heap?

This question was suggested by the author of the referenced video regarding the use of std::string in OpenGL. Specifically, he suggested that the willy-nilly use std::string in OpenGL can substantially slow dynamic scene changes. Now I am trying to better understand just how much memory is being allocated and where so that at least I know when it might be slowing a program.

Since I slightly modified this program, perhaps the code is not doing what I think it is doing, i.e., that I have made a programming mistake. If that is the case, I would appreciate the error(s) being identified.

9
  • I guess the 8 bytes have nothing to do with std::string, and for string lengths lower then 15 bytes std::string is using internal memory instead of allocating. Does empty int main () {} also allocate 8 bytes? Does main() { std::cout << ""; } also allocate 8 bytes? Commented Nov 25, 2019 at 15:58
  • Note that you are requiring 16 and 17 bytes, respectively, to include the terminating null character. Seeing as std::string allows small string optimization (which generally amounts to using two of the three pointer-sized members as character storage instead of their normal functionality, i.e. distinct behavior for 16 vs 17 bytes), the string should not be allocating anything in the first case. I assume your operator new is being called for something else than the string constructor. Commented Nov 25, 2019 at 15:59
  • 1
    Run the application in release mode. You will see there are 0 allocations done. Probably the memory was allocated for error-checking structures within the string class. Also, as of C++ 17, there is a way to make your strings faster, and that is to use std::string_view for getting a view into a string instead of needlessly creating them. Commented Nov 25, 2019 at 16:03
  • if you remove 'std::string name = "123456789012345";' (i.e. no string allocation at all), does it still show this 8 bytes allocation? Commented Nov 25, 2019 at 16:48
  • Remember small-string optimisation. Commented Nov 25, 2019 at 16:51

1 Answer 1

1

I don't know what purpose the 8 bytes was allocated for, but assuming a typical std::string implementation, there is no need for dynamic allocation whatsoever. String implementations implement "small string optimisation":

The idea is to treat the string object as a tagged union with the set of pointers to dynamic string as one member, and an array of characters of equivalent size as the other member. As long as the string fits inside sizeof(std::string), it is stored in that array member; otherwise the string is allocated dynamically, and the pointers are stored instead.


  1. That in the first case only 8 bytes of heap memory are being allocated for storing the string's pointer address and that the 15 characters of the string are stored on the stack?

The 8 bytes are probably not directly related to the string. I don't see a reason to store "string's pointer address" dynamically. Where would the address of the pointer be stored, and what would that achieve? Instead, the allocation may be related to some debugging feature.

Storing the 15 characters on stack is probably accurate.

Sign up to request clarification or add additional context in comments.

2 Comments

Because the app was run in debug mode, maybe the allocation was done to create structures used for error checking.
When run in x86 release mode, with std::string name = "123456789012345";, i.e., 15 characters, there are 0 allocations. It does appear that the debug mode is allocating memory for its own purposes. However, again in x86 release mode, when std::string name = "1234567890123456";, i.e., 16 characters, there is a 32 byte allocation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.