0

Calling new on a throwing constructor will not leak memory, since apparently all this is handled by the new operator. I'd assume that for user-defined new/delete operators this doesn't happen out of the box, but valgrind reports no memory leaks on my test programs (just that the process is terminating):

#include <iostream>

struct Widget
{
    Widget()
    {   
        std::cout << "\tctor\n";
        throw "up";
    }   

    void *operator new(size_t sz) 
    {   
        std::cout << "\tnew " << sz << " bytes\n";
        return malloc(sz);
    }   

    void operator delete(void *p) 
    {   
        std::cout << "\tdelete\n";
        free(p);
    }   
};

int main()
{
    auto a = new Widget;
    return 0;
}

How is memory deallocated in my case? Is the memory guaranteed to be deallocated when a constructor throws in the default new operator as well?

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
Lorah Attkins
  • 5,331
  • 3
  • 29
  • 63
  • You are confused about the new operator, and operator new. – Aykhan Hagverdili Mar 06 '21 at 10:35
  • @AyxanHaqverdili I am confused about the reasoning behind closing this question. A throwing constructor dooes not cause a memory leak, but apparently the same happens for custom new operators. I'm asking where the deallocation happens. Please run the program under valgrind yourself and check. Don't close questions you don't understand – Lorah Attkins Mar 06 '21 at 10:37
  • I didn't close your question. I personally don't think either of the duplicates are good. I was in the middle of writing an answer when the question was closed. – Aykhan Hagverdili Mar 06 '21 at 10:38
  • To put it simply, there is the "new operator" which you cannot overload. And there is the "operator new" which you can overload. The former is a part of the language and it uses your overloaded operators to enforce the logic. – Aykhan Hagverdili Mar 06 '21 at 10:40
  • 1
    @πάντα ῥεῖ these are terrible duplicates and looks like you didn't read the question beyond the title. – Aykhan Hagverdili Mar 06 '21 at 10:42
  • @AyxanHaqverdili Propose better ones then. It's all well explained in both of the linked duplicates. – πάντα ῥεῖ Mar 06 '21 at 10:43
  • @AyxanHaqverdili Sorry for assuming it was you. From what you said I managed to find an answer. Let me know if I'm wrong in the comments, cause I don't think whoever closed the question understands it enough to revise: So the Standard mandates for the new operator that "If initialization terminates by throwing an exception (e.g. from the constructor), if new-expression allocated any storage, it calls the appropriate deallocation function:". Since my overload (operator new) is being called from the new operator, I get this guarantee for free. Is this correct? – Lorah Attkins Mar 06 '21 at 11:00
  • Yes. This is correct. It calls your `operator delete` for you. – Aykhan Hagverdili Mar 06 '21 at 11:05
  • I'd add that https://stackoverflow.com/a/4421791/5980430 is probably the duplicate answer @πάνταῥεῖ suggest. – apple apple Mar 06 '21 at 13:49
  • @LorahAttkins The `void *operator new` doesn't call constructor, it simply has nothing to do with constructor (throw or not). – apple apple Mar 06 '21 at 14:00
  • @appleapple If you run the program you can see that the constructor is called http://coliru.stacked-crooked.com/a/6efa1547cfb9070f . The ctor is called after the memory allocation by the new expression. Can you please vote to reopen the question, you'd benefit from the answer as well. – Lorah Attkins Mar 06 '21 at 17:07
  • @LorahAttkins I have no problem understanding constructor being called (otherwise what can throw?). the problem is **the `void *operator new(size_t)`** has nothing to do with constructor – apple apple Mar 06 '21 at 17:08
  • @appleapple Yes, the call chain is triggered by the "new expression", but that is not what the question asks. The question is where the deallocation happens, and I think the answer is a couple of comments up. – Lorah Attkins Mar 06 '21 at 17:11
  • @LorahAttkins well just the same as normal operator new, why you think otherwise? – apple apple Mar 06 '21 at 17:13
  • as I said, the `void *operator new(size_t)` you implement simply has nothing to do with constructor throw or not. – apple apple Mar 06 '21 at 17:14
  • @appleapple is placement new the same case? Rhetorical question ... not all is obvious. I think you're just trying to cover the irrelevance of the first comment – Lorah Attkins Mar 06 '21 at 17:15
  • and the [link in this comment](https://stackoverflow.com/questions/66504682/deallocation-in-presence-of-a-throwing-constructor?noredirect=1#comment117570755_66504682) (one of the dupe) do explain it as *if a constructor throws during the evaluation of a new expression, the run-time system will return the memory to the operator delete matching the operator new*. Proper duplicate I'd say (maybe the question itself is too broad and I'm not sure SO can close dupe to answer or not, maybe the close voter @πάνταῥεῖ should add a comment link to the answer) – apple apple Mar 06 '21 at 17:22
  • @LorahAttkins which first comment? sorry but my fist comment in this thread is a suggest to duplicate answer? – apple apple Mar 06 '21 at 17:22
  • (repost the above 2 comments to add `@` `πάνταῥεῖ`) (not relevant to this question but does add space between @ and username effective to prevent a notification?) – apple apple Mar 06 '21 at 17:22

0 Answers0