What's virtual operator new/delete?

116 views Asked by At

Recently, I disassembled some DLL&PDB with llvm-pdbutil pretty --classes. But I don't have the source codes for this DLL.

In the output, I found some expressions in class body, mainly declarations of virtual operator new/delete which I'm not familar with. For example, in 2 classes, I found

// class 1
virtual void *operator new() = 0;
virtual void operator delete() = 0;

// class 2
virtual void *operator new(unsigned __int64 Size) = 0;
virtual void operator delete(void *result) = 0;

I don't know what are these and what may be the correspond C++ code for them, could somebody tell me more about them?

I tried copy and paste them directly into IDE, but the linting says "only nonstatic member functions may be virtual"; if I remove 'virtual', I got "pure specifier ('= 0') allowed only on virtual functions". So the compilation won't succeed.

I'm sure that the DLL is built with VS 2019, msvc on an x86_64 machine.


Appended:

I dived into the source codes of llvm-pdbutil 17.0.6, and found these functions are tagged virtual or even pure virtual because that the PDBSymbol is returns to be pure in get_pure in DIA SDK.

bool DIARawSymbol::isPureVirtual() const {
  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_pure);
}

But why? The doc says nothing about the definition of pure in this SDK.

2

There are 2 answers

1
Satoshic On

This is actually an overload of delete and new operators, you can do that in C++. You can read more about that here: https://en.cppreference.com/w/cpp/memory/new/operator_new. " =0 " after virtual means that the class is abstract and you are not able to create it(C++ difference between virtual = 0; and empty function)

0
Swift - Friday Pie On

The syntax virtual type function-id (argument-list) = 0; can exist only inside of definition of class-type and explicitly tells that there is no code for it by = 0, thus it's called pure in C++, SDK is not related to it.

If a class T contains any pure member, it is called "abstract class" and cannot be constructed, therefore there cannot be an object or variable, or returned value of type T. There can be a pointer to T, or reference to T (T*, T& or T&&), but they would refer to an object of an non-abstract type derived from T.

A derived class should implement - override - member function-id with an equivalent signature. Overriding implementation doesn't require word virtual, although modern style is add keyword override:

  // This code is not ISO-compliant!

  struct Base {
     virtual void *operator new() =  0;   
     virtual void *operator new(unsigned __int64 Size) = 0; // new[]
   };

   struct Derived : Base {
      void *operator new() override; // override is optional
      void *operator new(unsigned __int64 Size) override; // new[]
   };

I assume tht there is matching operator delete.

Now for the fun part - disassembler had generated a non-standard code. While some compilers support virtual operator new\delete used in combination with type erasure, ISO-C++ states that these operators are implicitly static. I don't remeber if MS compiler supports that in any mode though, conformance mode flag (/permissive) might be the key, if it does.