0

I am using g++ with the c++ 17 standard

In the accepted answer for question memset() or value initialization to zero out a struct? it states that

struct TestStruct
{
    int a;
    std::string b;
};

TestStruct t = {};  // OK

{
    TestStruct t1;
    memset(&t1, 0, sizeof t1);  // ruins member 'b' of our struct
}  // Application crashes here

whereas in my own testing the program does not crash at this point.

Example A:

struct TestStruct
{
  int a;
  std::string b;
};

TestStruct t1;
memset(&t1, 0, sizeof t1);

t1.b = "before";
std::cout << t1.b << std::endl;
std::cout << "after";

This prints

before

after

Example B:

struct TestStruct
{
  int a;
  std::string b;
};

TestStruct t1;
memset(&t1, 0, sizeof t1);

t1.b = "";
std::cout << t1.b << std::endl;
std::cout << "after";

This prints nothing as the program crashes directly after t1.b = "";

For the sake of thoroughness I also tested with t1 going out of scope as in the referenced question

struct TestStruct
{
  int a;
  std::string b;
};

{
  TestStruct t1;
  memset(&t1, 0, sizeof t1);

  t1.b = "before";
  std::cout << t1.b << std::endl;
  std::cout << "after" << std::endl;
}
std::cout << "eventually";

prints

before

after

eventually

My main question is, why does example B crash where example A does not?

  • 5
    You can only use `memset` on objects that are trivial. `std::string` is not a trivial type. – NathanOliver Jun 24 '22 at 15:30
  • You can use `std::is_trivially_copyable::value` to see if `TestStruct` complies with [`std::memset`](https://en.cppreference.com/w/cpp/string/byte/memset) requirements. (Spoiler: it does not. q.v. [`std::is_trivially_copyable`](https://en.cppreference.com/w/cpp/types/is_trivially_copyable)) – Eljay Jun 24 '22 at 15:32
  • 2
    The program has undefined behavior meaning anything could happen including but not limited to the program giving your expected output or even crashing. Don't rely(or make conclusions based on) on the output of a program that has UB. – Jason Jun 24 '22 at 15:34

0 Answers0