2
struct Person {
   std::string name;
   int id;
};
struct Community {
   std::string name;
   Person people[2];
};

Community* makeCommunity() {
   Community* c = (Community*)operator new(sizeof(Community), std::nothrow);
   if(!c) {
      std::cout << "Failed to allocate" << std::endl;
      std::exit(0);
   }
   c->name = "Community Name";
   c->people[0].name = "Person1";
   c->people[0].id = 1;
   //Run-time encountered here.
   c->people[1].name = "Person2";
   c->people[1].id = 2;
   return c;
}

I'm currently learning C++ and I was testing code similar to above code when the program encountered a runtime error and crashed when it tries to execute c->people[1].name = "Person1"; in the aforementioned function. Yet, this works fine when I allocate memory as:

Community* c = new Community(std::nothrow);

I am puzzled by that fact that c->people[0].name = "Person1"; executes perfectly, but c->people[1].name = "Person2"; fails at runtime when memory is allocated for Community as:

Community* c = (Community*)std::operator new(sizeof(Community), std::nothrow);

Can someone shed some light on this?

Manchu Ratt
  • 177
  • 1
  • 5
  • 5
    Why are you allocating like that? Do you think your constructor is being called or not? Do you think the memory returned is actually an object or just a blob of uninitialized memory? Do you know what placement new is? – Retired Ninja Jan 21 '18 at 21:07
  • Yo might be skipping the initialization of `name` and breaking its `operator=`? I don’t really know C++ though – Ry- Jan 21 '18 at 21:08
  • 3
    Out of interest, why haven't you just written `Community c;` and go from there? What are you hoping to achieve here? – Tas Jan 21 '18 at 21:10
  • I am allocating this way because I was just testing all variations of "operator new()" as way of learning. From what I've read so far, the constructor should not be executed with this variation, but I couldn't understand why it didn't fail for the first array element. The memory returned from new() is an blob of uninitialized memory is my understanding. – Manchu Ratt Jan 21 '18 at 21:20
  • At what point in your code do you think you actually have a `Community` object? Calling `new` just allocates memory, right? – David Schwartz Jan 21 '18 at 23:08

1 Answers1

1

The call

Community* c = (Community*)operator new(sizeof(Community), std::nothrow);

does not create an object of type Community correctly. It just allocates memory for it. You need to use placement new operator to correctly initialize the object.

Using *c as a valid Community is cause for undefined behavior.

If you must use operator new, I suggest changing that line to:

void* ptr = operator new(sizeof(Community), std::nothrow);
Community* c = new (ptr) Community;     
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • My initial assumption was that this was caused by the constructor not running, but I have not yet learned about them. Thanks a lot. – Manchu Ratt Jan 21 '18 at 21:24
  • 4
    @ManchuRatt picking language features at random is not a good strategy for learning a language as you've found out. I recommend reading a book: https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list Any decent book will teach you about constructors and initialisation before introducing operator new. – eerorika Jan 21 '18 at 21:44