21

I have a massive structure where the entire contents is scalar variables, enumerations, and arrays of scalars (stack-based) with the exception of one std::string variable.

Now, here's my question...

Can I memset the structure to 0 for its whole size (like I would if it was simply all scalars), or is that not possible with the std::string being in there? I'm not sure what memset would do to its internal representation.

And if you're going to say its good/bad please explain why - I'd like to know why it is the way it is :)

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
John Humphreys
  • 37,047
  • 37
  • 155
  • 255

3 Answers3

29

No, you cant, it would overwrite the internal state of the string and make bad things happen. You could wrap all the POD stuff in a seperate struct and put that in your current one, that way you could memset that and let the string default construct.

Edit: Just to clarify, the string will almost certainly be storing a pointer to the memory its allocated for storage. The string's constructor will always have run before you can memset it (even if you memset this in the constructor of your type, the string constructor would run first). So you would be overwriting this pointer value, and instead of pointing to its storage, it would a pointer to NULL, or some other almost definitely invalid value.

Node
  • 3,443
  • 16
  • 18
  • 1
    Not arguing `memset`ting an `std::string` to 0 is a bad idea, but it might actually work, assuming your `std:string` implementation does not allocate memory on construction. I'd imagine most `std::string`s have 3 pointers (begin, end, capacity) and a variable for size. If no allocation has been done it should be safe to set all of these to 0. Needless to say this would be non-portable. – Praetorian Jul 29 '11 at 20:08
  • Best case, by overwriting the pointers, you leak any memory allocated by the string. – Nemo Jul 29 '11 at 20:18
  • 1
    @Praetorian - you're right, but its such a terrible idea i'd rather class it as something you can't do. – Node Jul 29 '11 at 22:18
  • 1
    @Node I agree. Another thing I forgot when making my comment was if `std::string` derives from a base class with virtual functions then memsetting would overwrite the v-table and screw everything up. I'm not sure whether there's anything in the standard that prevents std::string` base classes from having virtual functions. – Praetorian Jul 29 '11 at 22:26
5

Here's an exotic idea: Suppose your class Foo has lots of primitive members which remain uninitialized in Foo's constructor, with the exception of one string:

class Foo
{
  int a;
  double b;
  std::string s;
};

The constructor Foo::Foo() will correctly initialize the string, but it won't care for anything else. So, let's zero out the memory before we construct!

void * addr = ::operator new(sizeof(Foo));
std::memset(addr, 0, sizeof(Foo));
Foo * p = new (addr) Foo;

// later

p->~Foo();
::operator delete(addr);

Of course it would be cleaner to just initialize all the members to zero in the constructor, but perhaps you have your own reasons that you don't want to create a custom constructor.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
-1

Zeroing std::string member is very bad idea, it will cause memory leak! Never do this!

  • 2
    This question has been answered in far more details for years. This adds nothing to the discussion. – ShadowRanger Nov 10 '18 at 02:04
  • 1
    Yes, but I spent 2 hours figuring out where's leak. I think, it will be interesting for people to know that it can cause leak – GamerDeveloper Nov 10 '18 at 12:40
  • 1
    The statement is incorrect. There is no requirement for a conforming implementation to cause a leak here. Indeed, the language specification makes **no promise at all** as to what the behavior should be. The behavior is thus undefined. Leaking memory is a valid form of undefined behavior, as much as *not* leaking memory is a valid form. – IInspectable Mar 18 '22 at 09:04