Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the empty base class optimization (EBO) is not working in MSVC?

Why is the empty base class optimization (EBO) not being fully applied in Visual C++?

If I have a lot of base classes, is there any way for me to help the compiler make this optimization?

#include <iostream>

struct T1 { };
struct T2 { };
struct T3 { };
struct T4 { };
struct T5 { };
struct T6 { };

struct Test : T1, T2, T3, T4, T5, T6 { };

int main() { std::cout << sizeof(Test); }   // Prints 5
like image 585
user541686 Avatar asked Oct 03 '12 03:10

user541686


3 Answers

This is a longstanding bug in the Visual C++ compiler. When a class derives from multiple empty base classes, only the initial empty base class will be optimized using the empty base optimization (EBO).

This issue was reported on Microsoft Connect in 2006: Empty Base Optimization Not Working Properly. At the moment, old bugs are not visible on Microsoft Connect. I am told that this is a temporary issue, though I do not know when it will be resolved. In the meantime, the following is the response to the bug from Jonathan Caves, who is one of the developers on the Visual C++ compiler team:

Hi: unfortunately even though this is a bug in the Visual C++ object model we are unable to fix it at this time given that fixing it would potentially break a lot of existing programs as the sizes of objects would change. Hopefully in the future we may be able to address this issue but not for the next release of the product.

Thanks for reporting the issue.

like image 70
James McNellis Avatar answered Oct 20 '22 16:10

James McNellis


The 'official' stance is MSVC will only do EBO for single inheritance, unfortunately the bug report where this is stated was deleted by MS, so all that remains is an older question on MSDN that points it out and references the now deleted bug report.

like image 34
Necrolis Avatar answered Oct 20 '22 16:10

Necrolis


Since Visual Studio 2017 Update 2, there is a fix for this... but is it disabled by default. And you have to explicitly enable it for every class separately:

    struct __declspec(empty_bases) Test : T1, T2, T3, T4, T5, T6 { };
    //     ^^^^^^^^^^^^^^^^^^^^^^^

    static_assert(1 == sizeof(Test));

Sadly, this still holds true even for /std:c++latest and /permissive- even in Visual Studio 2019: There is no way of setting it globally.

like image 8
Tobi Avatar answered Oct 20 '22 16:10

Tobi