std::string with no free store memory allocation - c++

I have a question very similar to
How do I allocate a std::string on the stack using glibc's string implementation?
but I think it's worth asking again.
I want an std::string with local storage that overflows into the free store. std::basic_string provides an allocator as a template parameter, so it seems like the thing to do is to write an allocator with local storage and use it to parameterize the basic_string, like so:
std::basic_string<
char,
std::char_traits<char>,
inline_allocator<char, 10>
>
x("test");
I tried to write the inline_allocator class that would work the way you'd expect: it reserves 10 bytes for storage, and if the basic_string needs more than 10 bytes, then it calls ::operator new(). I couldn't get it to work. In the course of executing the above line of code, my GCC 4.5 standard string library calls the copy constructor for inline_allocator 4 times. It's not clear to me that there's a sensible way to write the copy constructor for inline_allocator.
In the other StackOverflow thread, Eric Melski provided this link to a class in Chromium:
http://src.chromium.org/svn/trunk/src/base/stack_container.h
which is interesting, but it's not a drop-in replacement for std::string, because it wraps the std::basic_string in a container so that you have to call an overloaded operator->() to get at the std::basic_string.
I can't find any other solutions to this problem. Could it be that there is no good solution? And if that's true, then are the std::basic_string and std::allocator concepts badly flawed? I mean, it seems like this should be a very basic and simple use case for std::basic_string and std::allocator. I suppose the std::allocator concept is designed primarily for pools, but I think it ought to cover this as well.
It seems like the rvalue-reference move semantics in C++0x might make it possible to write inline_allocator, if the string library is re-written so that basic_string uses the move constructor of its allocator instead of the copy constructor. Does anyone know what the prospect is for that outcome?
My application needs to construct a million tiny ASCII strings per second, so I ended up writing my own fixed-length string class based on Boost.Array, which works fine, but this is still bothering me.

Andrei Alexandrescu, C++ programmer extraordinaire who wrote "Modern C++ Design" once wrote a great article about building different string implementations with customizable storage systems. His article (linked here) describes how you can do what you've described above as a special case of a much more general system that can handle all sorts of clever memory allocation requirements. This doesn't talk so much about std::string and focuses more on a completely customized string class, but you might want to look into it as there are some real gems in the implementation.

C++2011 is really going to help you here :)
The fact is that the allocator concept in C++03 was crippled. One of the requirement was that an allocator of type A should be able to deallocate memory from any other allocator from type A... Unfortunately this requirement is also at odds with stateful allocators each hooked to its own pool.
Howard Hinnant (who manages the STL subgroup of the C++ commitee and is implementing a new STL from scratch for C++0x) has explored stack-based allocators on his website, which you could get inspiration from.

This is generally unnecessary. It's called the "short string optimization", and most implementations of std::string already include it. It may be hard to find, but it's usually there anyway.
Just for example, here's the relevant piece of sso_string_base.h that's part of MinGW:
enum { _S_local_capacity = 15 };
union
{
_CharT _M_local_data[_S_local_capacity + 1];
size_type _M_allocated_capacity;
};
The _M_local_data member is the relevant one -- space for it to store (up to) 15 characters (plus a NUL terminator) without allocating any space on the heap.
If memory serves, the Dinkumware library included with VC++ allocates space for 20 characters, though it's been a while since I looked, so I can't swear to that (and tracking down much of anything in their headers tends to be a pain, so I prefer to avoid looking if I can).
In any case, I'd give good odds that you've been engaged in that all-too-popular pass-time known as premature optimization.

I believe the code from Chromium just wraps things into a nice shell. But you can get the same effect without using the Chromium wrapper container.
Because the allocator object gets copied so often, it needs to hold a reference or pointer to the memory. So what you'd need to do is create the storage buffer, create the allocator object, then call the std::string constructor with the allocator.
It will be a lot wordier than using the wrapper class but should get the same effect.
You can see an example of the verbose method (still using the chromium stuff) in my question about stack vectors.

Related

C++ allocators_trait::construct: motivation, trade-offs in ignoring

I'm wrestling with some pain being caused by std::allocator_traits::construct. In order for a container to be a "conforming" user of the allocator concept, it needs to use construct rather than placement new to construct objects. This is very sticky for me. Currently I have a class (class A) that is designed to be allocator aware, and at some point it needs to create another instance of some other class (class B) in allocated memory. The problem is that class B implements the construction of the new object. If I could use placement new, this wouldn't be an issue: A would handle allocation, pass B the memory address, and B would construct into that. But since the construction needs to be performed via construct, I need to inject the allocator type into B, templating it, which creates a huge mess.
It's bad enough that I am seriously considering just using placement new, and static asserting that my instance of the allocator does not have a construct method (note that the static construct function calls the instance method if it exists, otherwise it calls placement new). I have never felt the tiniest urge to write a construct method for an allocator. The cost of making this part of the allocator concept seems very high to me; construction has gotten entangled with allocation, where allocators were supposed to help separate them. What justifies the existence of construct/destruct? Insight into the design decision, examples of real (not toy) use cases, or thoughts on the gravity of electing to simply use placement new appreciated.
There is a similar question; std::allocator construct/destroy vs. placement new/p->~T(). It was asked quite a long time ago, and I don't find the answer accepted there as sufficient. Logging is a bit trite as a use case, and even then: why is the allocator logging the actual construction of objects? It can log allocations and deallocations in allocate and deallocate, it doesn't answer the question in the sense of: why was construction made a province of the allocator in the first place? I'm hoping to find a better answer; it's been quite a few years and much about allocators has changed since then (e.g. allocators being stateful since 11).
A few points:
There really isn't a std container concept. The container requirements tables in the standard are there to document the containers specified by the standard.
If you have a container that wants to interact with std::allocator_traits<Alloc>, all you have to do is assume that Alloc conforms to the minimum C++11 allocator requirements and interact with it via std::allocator_traits<Alloc>.
You are not required to call std::allocator_traits<Alloc>::construct.
You are forbidden from calling Alloc::construct because it may not exist.
The standard-specified containers are required to call std::allocator_traits<Alloc>::construct only for container::value_type, and are forbidden from using std::allocator_traits<Alloc>::construct on any other types the container may need to construct (e.g. internal nodes).
Why was construct included in the "allocator concept" way back in C++98?
Probably because the committee at the time felt that this would ease dealing with x86 near and far pointers -- a problem that no longer exists today.
That being said, std::scoped_allocator_adaptor is a modern real-world example of an allocator that customizes both construct and destroy. For the detailed specification of those customizations I point you towards the latest C++1z working draft, N4567. The spec is not simple, and that is why I'm not attempting to reproduce it here.

worst that can happen if i don't obey the stateless custom allocators dogma?

I need to create a custom allocator for std:: objects (particularly and initially for std::vector) but it might eventually come to use others
The reason I need to create a custom allocator is that I need to track allocated (heap & stack) resources by individual components of the application (this is an inherent feature of the application). I will need the custom allocator to monitor the heap portion of the resources, so it is essential that I'm able to pass to the std::vector constructor something like
trackerId idToTrackUsage;
myAlloca<int> allocator(idToTrackUsage);
vector<int> Foo( allocator );
However, after reading a bit I found this little bomb about the STL / C++ standard (see references) saying that all allocator instances of a given type should be equivalent (that is that == should return true for any two instances) and, most terminal; any allocator should be able to deallocate memory allocated by any other instance (that is, without having a way to know what that other instance might be). In short, allocators cannot have state.
So I'm trying to find the best way around this. Any clever ideas? I really really REALLY don't want to have to keep a custom version of std::vector around.
EDIT: i read about scoped allocators for c++0x on http://www2.research.att.com/~bs/C++0xFAQ.html#scoped-allocator but i couldn't really get far into understanding how this applies to my problem. If anyone thinks c++0x alleviates this problem, please comment
References:
Allocator C++ article in Wikipedia
Some random further reading courtesy of Google
Aside from the obvious answer ("if you violate any requirement, that's undefined behavior, good night and thanks for playing"), I imagine the worst that would likely happen, is that the vector implementation can rely on the requirement that "all instances of the allocator class are interchangeable" in the obvious way:
vector(const Allocator &youralloc = Allocator()) {
const Allocator hawhaw;
// use hawhaw and ignore youralloc.
// They're interchangeable, remember?
}
Looking at the source, GCC's vector implementation (which I think is based eventually on SGI's original STL implementation) does sort-of store a copy of the allocator object passed into that constructor, so there's some hope that this won't happen.
I'd say try it and see, and document what you've done very carefully, so that anyone attempting to use your code on an implementation that you haven't checked, knows what's going on. Implementers are encouraged in the standard to relax the restrictions on allocators, so it would be a dirty trick to make it look as though they're relaxed when really they aren't. Which doesn't mean it won't happen.
If you're really lucky, there's some documentation for your container implementation that talks about allocators.
You could, of course, leave a pointer to whatever state you need in any allocated blocks. This does of course mean that any per-block state must be stored in that block, and the allocator instances would act more like handles than actual objects in as of themselves.
Making the allocator state static would do the trick, if you're able to work with that. It does mean that all allocators of that type will have to share their state, but from your requirements, that sounds like it could be acceptable
To respond to your edit: yes, in C++0x or C++11, allocators can have state.

Creating a scoped custom memory pool/allocator?

Would it be possible in C++ to create a custom allocator that works simply like this:
{
// Limit memory to 1024 KB
ScopedMemoryPool memoryPool(1024 * 1024);
// From here on all heap allocations ('new', 'malloc', ...) take memory from the pool.
// If the pool is depleted these calls result in an exception being thrown.
// Examples:
std::vector<int> integers(10);
int a * = new int [10];
}
I couldn't find something like this in the boost libraries, or anywhere else.
Is there a fundamental problem that makes this impossible?
You would need to create a custom allocator that you pass in as a template param to vector. This custom allocator would essentially wrap the access to your pool and do whatever size validations that it wants.
Yes you can make such a construct, it's used in many games, but you'll basically need to implement your own containers and call memory allocation methods of that pool that you've created.
You could also experiment with writing a custom allocator for the STL containers, although it seems that that sort of work is generally advised against. (I've done it before and it was tedious, but I don't remember any specific problems.)
Mind- writing your own memory allocator is not for the faint of heart. You could take a look at Doug Lea's malloc, which provides "memory spaces", which you could use in your scoping construct somehow.
I will answer a different question. Look at 'efficient c++' book. One of the things they discuss is implementing this kind of thing. That was for a web server
For this particular thing you can either mess at the c++ layer by overriding new and supplying custom allocators to the STL.
Or you can mess at the malloc level, start with a custom malloc and work from there (like dmalloc)
Is there a fundamental problem that makes this impossible?
Arguing about program behavior would become fundamentally impossible. All sorts of weird issues will come up. Certain sections of the code may or may not execute though this will seeminly have no effect on the next sections which may work un-hindered. Certain sections may always fail. Dealing with the standard-library or any other third party library will become extremely difficult. There may be fragmentations at run-time at times and at times not.
If intent is that all allocations within that scope occur with that allocator object, then it's essentially a thread-local variable.
So, there will be multithreading issues if you use a static or global variable to implement it. Otherwise, not a bad workaround for the statelessness of allocators.
(Of course, you'll need to pass a second template argument eg vector< int, UseScopedPool >.)

How is std::string implemented?

I am curious to know how std::string is implemented and how does it differ from c string?If the standard does not specify any implementation then any implementation with explanation would be great with how it satisfies the string requirement given by standard?
Virtually every compiler I've used provides source code for the runtime - so whether you're using GCC or MSVC or whatever, you have the capability to look at the implementation. However, a large part or all of std::string will be implemented as template code, which can make for very difficult reading.
Scott Meyer's book, Effective STL, has a chapter on std::string implementations that's a decent overview of the common variations: "Item 15: Be aware of variations in string implementations".
He talks about 4 variations:
several variations on a ref-counted implementation (commonly known as copy on write) - when a string object is copied unchanged, the refcount is incremented but the actual string data is not. Both object point to the same refcounted data until one of the objects modifies it, causing a 'copy on write' of the data. The variations are in where things like the refcount, locks etc are stored.
a "short string optimization" (SSO) implementation. In this variant, the object contains the usual pointer to data, length, size of the dynamically allocated buffer, etc. But if the string is short enough, it will use that area to hold the string instead of dynamically allocating a buffer
Also, Herb Sutter's "More Exceptional C++" has an appendix (Appendix A: "Optimizations that aren't (in a Multithreaded World)") that discusses why copy on write refcounted implementations often have performance problems in multithreaded applications due to synchronization issues. That article is also available online (but I'm not sure if it's exactly the same as what's in the book):
http://www.gotw.ca/publications/optimizations.htm
Both those chapters would be worthwhile reading.
std::string is a class that wraps around some kind of internal buffer and provides methods for manipulating that buffer.
A string in C is just an array of characters
Explaining all the nuances of how std::string works here would take too long. Maybe have a look at the gcc source code http://gcc.gnu.org to see exactly how they do it.
There's an example implementation in an answer on this page.
In addition, you can look at gcc's implementation, assuming you have gcc installed. If not, you can access their source code via SVN. Most of std::string is implemented by basic_string, so start there.
Another possible source of info is Watcom's compiler
The c++ solution for strings are quite different from the c-version. The first and most important difference is while the c using the ASCIIZ solution, the std::string and std::wstring are using two iterators (pointers) to store the actual string. The basic usage of the string classes provides a dynamic allocated solution, so in the cost of CPU overhead with the dynamic memory handling it makes the string handling more comfortable.
As you probably already know, the C doesn't contain any built-in generic string type, only provides couple of string operations through the standard library. One of the major difference between C and C++ that the C++ provides a wrapped functionality, so it can be considered as a faked generic type.
In C you need to walk through the string if you would like to know the length of it, the std::string::size() member function is only one instruction (end - begin) basically. You can safely append strings one to an other as long as you have memory, so there is no need to worry about the buffer overflow bugs (and therefore the exploits), because the appending creates a bigger buffer if it is needed.
As somebody told here before, the string is derivated from the vector functionality, in a templated way, so it makes easier to deal with the multibyte-character systems. You can define your own string type using the typedef std::basic_string specific_str_t; expression with any arbitary data type in the template parameter.
I think there are enough pros and contras both side:
C++ string Pros:
- Faster iteration in certain cases (using the size definitely, and it doesn't need the data from the memory to check if you are at the end of the string, comparing two pointers. that could make a difference with the caching)
- The buffer operation are packed with the string functionality, so less worries about the buffer problems.
C++ string Cons:
- due to the dynamic memory allocation stuff, the basic usage could cause impact on the performance. (fortunately you can tell to the string object what should be the original buffer size, so unless you are exceed it, it won't allocate dynamic blocks from the memory)
- often weird and inconsistent names compared to other languages. this is the bad thing about any stl stuff, but you can use to it, and it makes a bit specific C++ish feeling.
- the heavy usage of the templating forces the standard library to use header based solutions so it is a big impact on the compiling time.
That depends on the standard library you use.
STLPort for example is a C++ Standard Library implementation which implements strings among other things.

How do I allocate a std::string on the stack using glibc's string implementation?

int main(void)
{
std::string foo("foo");
}
My understanding is that the above code uses the default allocator to call new. So even though the std::string foo is allocated on the stack the internal buffer inside of foo is allocated on the heap.
How can I create a string that is allocated entirely on the stack?
I wanted to do just this myself recently and found the following code illuminating:
Chronium's stack_container.h
It defines a new std::allocator which can provide stack-based allocation for the initial allocation of storage for STL containers. I wound up finding a different way to solve my particular problem, so I didn't actually use the code myself, but perhaps it will be useful to you. Do be sure to read the comments in the code regarding usage and caveats.
To those who have questioned the utility and sanity of doing this, consider:
Oftentimes you know a priori that your string has a reasonable maximum size. For example, if the string is going to store a decimal-formatted 32-bit integer,you know that you do not need more than 11 characters to do so. There is no need for a string that can dynamically grow to unlimited size in that case.
Allocating from the stack is faster in many cases than allocating from the heap.
If the string is created and destroyed frequently (suppose it is a local variable in a commonly used utility function), allocating from the stack instead of the heap will avoid fragmentation-inducing churn in the heap allocator. For applications that use a lot of memory, this could be a game changer.
Some people have commented that a string that uses stack-based allocation will not be a std::string as if this somehow diminishes its utility. True, you can't use the two interchangeably, so you won't be able to pass your stackstring to functions expecting a std::string. But (if you do it right), you will be able to use all the same member functions on your stackstring that you use now on std::string, like find_first_of(), append(), etc. begin() and end() will still work fine, so you'll be able to use many of the STL algorithms. Sure, it won't be std::string in the strictest sense, but it will still be a "string" in the practical sense, and it will still be quite useful.
The problem is that std::basic_string has a template parameter for the allocator. But std::string is not a template and has no parameters.
So, you could in principle use an instantiation of std::basic_string with an allocator that uses memory on the stack, but it wouldn't be a std::string. In particular, you wouldn't get runtime polymorphism, and you couldn't pass the resulting objects into functions expecting a std::string.
You can't. Except...
std::string is an instantiation of
std::basic_string<class CharType,
class Traits=char_traits<CharType>,
class Allocator=allocator<CharType> >
You could conceivably define an Allocator class that uses alloca for memory management. This would only work if the Allocator itself, and the basic_string methods that invoke it directly or indirectly, are all inline. A basic_string object created with this allocator would not be a std::string, but it would behave (mostly) like it. However, this would be a fair amount of work for limited gains. Specifically, using this class to return values from a function would be a career-limiting move.
I have no idea why you or anyone else would want to do this.
I suspect that doing such a thing would be difficult to do, I wonder why you want to do it? To allocate something entirely on the stack, the compiler needs to know at compile time what the exact size of the thing is - in your example it would need to know not only the size of the std::string metadata, but also the size of the string data itself. This isn't too flexible, you would probably need different string types depending on the size of the string data you are wanting to include in it - not that it would be impossible to do, just it would tend to complicate things up a bit.
std::string will always manage it's internal storage with new/delete.
Not sure why your question contains glibc’s string implementation. The string implementation of the c++ standard library has nothing to do with glibc.
The only way to store a string on the stack is to use a C char array on the stack (like what Shhnap outlined). But that's probably not what you want anyway :-)