0

Suppose I have the following:

std::string TestFragmentation()
{
    std::vector<char> buffer(500);
    SomeCApiFunction( &buffer[0], buffer.size() ); // Sets buffer to null-terminated string data
    return &buffer[0];
}

Will the above vector, which allocates memory on the heap, be a cause of memory fragmentation? My understanding of fragmentation is that it only really occurs if you have small, long-lived allocations between larger, more short lived allocations (or vice-versa).

I don't want to prematurely optimize this situation, so I'd like to hear what the general take on code like this should be. I know various experts do not recommend putting large buffers on the stack (that's what the heap is for, after all), so that is usually what I think of first when I write code like this. Fragmentation is normally something that requires analysis. What should my state of mind be here?

trincot
  • 317,000
  • 35
  • 244
  • 286
void.pointer
  • 24,859
  • 31
  • 132
  • 243
  • I wouldn't consider 500 bytes a "large buffer". – Mark Ransom Apr 16 '12 at 20:27
  • This is entirely implementation defined as it depends on the behavior of your standard library's default allocator. – ildjarn Apr 16 '12 at 20:27
  • @ildjarn I suppose we should stick to some simple implementation for the purposes of this question. Technically speaking you are correct but I'm looking for a general perspective here. – void.pointer Apr 16 '12 at 20:28
  • TBH, I'm not actually sure what is going on here. The vector class is a wrapped-up dynamic array with internal metadata, the function declares it returns a std::string but, instead, returns a pointer to data that belongs to the vector that is about to be destroyed? Do I understand this right? I don't understand or follow code like this - I find it difficult to know what is being copied to what and what will be destroyed when :( I would have new()ed the vector and returned its pointer as a *vector. – Martin James Apr 16 '12 at 20:51
  • @MartinJames, it's relying on an implicit conversion from `char *` to `std::string`, same as `return "answer";`. `std::vector` makes a very good smart pointer for a buffer. – Mark Ransom Apr 16 '12 at 21:04
  • @MartinJames It returns a string because the function says it returns a string. It's the same as `return std::string(&buffer[0]);`. The string must be constructed while `buffer` is still in scope because it references `buffer` and you can't reference a name that's out of scope. So there's no issue. – David Schwartz Apr 16 '12 at 21:20

1 Answers1

3

If this is the most natural way to express what this code does, then you should do it this way. Unless you have a very unusual situation you haven't told us about, memory fragmentation shouldn't even be on your radar screen yet.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Thanks. Could you provide some examples as to when memory fragmentation _would_ be on my radar screen? – void.pointer Apr 16 '12 at 20:27
  • 1
    When you actually see memory allocations fail and have ruled out a resource leak. When you are actually designing memory management code. When you are dealing with specialized environments other than general-purpose computing such as embedded systems. When you are dealing with special kinds of memory (such as in-kernel applications with limited amounts of memory in specialized hardware or dealing with locked memory for Windows overlapped operations on older versions of Windows). – David Schwartz Apr 16 '12 at 20:30
  • Thanks David, great points. In the end though, I went with `boost::array` because for such a simple task, I didn't want the performance impact of running through the memory manager. – void.pointer Apr 16 '12 at 20:34
  • 2
    That's fine. I don't think it will make a bit of difference, but if the code reads just as naturally either way, then there's no harm. But don't pervert your code to avoid an allocation. Modern allocators are fast and the value of clean code that is easy to understand, debug, and maintain is significant. – David Schwartz Apr 16 '12 at 20:36