1

Here is the MCVE:

#include <iostream>
#include <string>

using namespace std;

class Obj {
public:
    Obj() { cout << "Obj()" << endl; }
    ~Obj() { cout << "~Obj()" << endl; }
    void* operator new(size_t sz){
        return ::operator new(sz);
    }
    void operator delete(void* p) {
        ::operator delete(p);
    }
private:
    friend class MyClass;
    void* operator new(size_t, void*);
    void operator delete(void*, size_t);
};

class MyClass {
public:
    MyClass() : m_(new Obj) {
        cout << "MyClass()" << endl;
    }
    ~MyClass() {
        cout << "~MyClass()" << endl;
        delete m_;
    }
private:
    const Obj * m_;
};

int main()
{
    cout << "Started" << endl;
    MyClass o;
    cout << "Finished" << endl;
    return 0;
}

Building with MSVC 2015 (14.0):

error LNK2019: unresolved external symbol "private: static void __cdecl Obj::operator delete(void *,unsigned int)" (??3Obj@@CAXPAXI@Z) referenced in function __unwindfunclet$??0MyClass@@QAE@XZ$0

Building with MSVC 2013 (12.0): OK

Building with GCC 5.2: OK

Questions:

Why?

How to fix / work around?

P.S.

Original file in QtScript project.

Community
  • 1
  • 1
Dmitry Sokolov
  • 3,118
  • 1
  • 30
  • 35
  • 1
    Where is `void operator delete(void*, size_t)`? – Neil Kirk Oct 29 '15 at 18:09
  • @NeilKirk Privates of `class Obj`. – cadaniluk Oct 29 '15 at 18:10
  • Comment the declarations out? – NathanOliver Oct 29 '15 at 18:11
  • @Drop Could you please provide your build log with the option `/nologo` turned off? – Dmitry Sokolov Oct 29 '15 at 18:44
  • http://pastebin.com/4q34YYqi – Ivan Aksamentov - Drop Oct 29 '15 at 18:49
  • 1
    Compilation fails if you set exception handling mode with `/EHsc`. Maybe MSVC expects `noexcept` overloads of operators. Language lawyer wanted. Meanwhile check [operator new](http://en.cppreference.com/w/cpp/memory/new/operator_new), [operator delete](http://en.cppreference.com/w/cpp/memory/new/operator_delete) – Ivan Aksamentov - Drop Oct 29 '15 at 18:51
  • You should also explicitly point out platform you are building for (for now MSVC supports x86, x86_64 and ARM). Exceptions are handled differently on different platforms. My log above is for x86_64 – Ivan Aksamentov - Drop Oct 29 '15 at 18:56
  • @Drop Thanks! I got this error for both platforms. But when I've turned off `/EHsc` mode the build is completed only with warnings. – Dmitry Sokolov Oct 29 '15 at 19:01
  • The issue is that you only provide 2 overloads of each operator and in C++ there are 12 possible overloads of `new` and 18 of `delete` (see links above). Some of them are used in present of exceptions and others -- without them. I think that problem arises on MSVC and not on GCC because it uses anotther exception handling scheme. It compiles on MSVC12 because it does not support C++11 [`noexcept`](http://en.cppreference.com/w/cpp/language/noexcept). I might be completely wrong. Standard gazers are still welcome. – Ivan Aksamentov - Drop Oct 29 '15 at 19:05
  • 1
    Overriding `new` and `delete` is not as straightforward as you might think. I would strongly advice you against it. See also a 3-act opera on: [How should I write ISO C++ Standard conformant custom new and delete operators?](http://stackoverflow.com/questions/7194127/how-should-i-write-iso-c-standard-conformant-custom-new-and-delete-operators) – Ivan Aksamentov - Drop Oct 29 '15 at 19:09

1 Answers1

1

Taking into account Breaking Changes in Visual C++ 2015 I incline to the follow decision:

class Obj {
...
private:
    friend class MyClass;
    void* operator new(size_t, void*);
#if defined(_MSC_VER) && _MSC_VER >= 1900
    enum class Obj_tag : size_t {};
    void operator delete(void*, Obj_tag);
#else
    void operator delete(void*, size_t);
#endif
};

So, the following code

#ifdef ERROR_TEST
char buf[1024] = { 0 };
Obj * o1 = reinterpret_cast<Obj*>(buf);
new (o1) Obj;
#endif
MyClass o2;

is compiled in the same way both with MSVC 2012 and with MSVC 2015. (When ERROR_TEST is defined there is the error C2248: 'Obj::operator new': cannot access private member declared, and when is not - all OK)

Dmitry Sokolov
  • 3,118
  • 1
  • 30
  • 35