Информация об изменениях

Сообщение Re[2]: детские грабли: declspec novtable от 10.10.2014 13:35

Изменено 10.10.2014 13:36 Кодт

Здравствуйте, rus blood, Вы писали:

RB>If you attempt to instantiate a class marked with novtable and then access a class member, you will receive an access violation (AV).


Не AV, а любое другое UB.

#include <stdio.h>

struct __declspec(novtable) A
{
    A() { printf("%p A::ctor\n", this); }
    ~A() { printf("%p A::dtor\n", this); }

    virtual void foo() { printf("%p A::foo\n", this); }
    void bar() { A::foo(); }
    void buz() { foo(); }
};

struct B
{
    virtual void hello() { printf("%p B::hello\n", this); }
};

typedef int (*FUN)();
FUN pvfc_table[1] = { _purecall };

int surprize() { printf("surprize!\n"); return 0; }
FUN surprize_table[1] = { surprize };

template<FUN* table>
struct С
{
    С() : p(table) {}
    FUN* p;
};

void runA()
{
    A a;
    a.foo();
    a.bar();
    a.buz();
}

template<class T>
void runT()
{
    T t;
}

int main()
{
    __try
    {
        // выберите любой вариант
        runT< B >();
        runT< C<nullptr> >();
        runT< C<pvfc_table> >();
        runT< C<surprize_table> >();
        runT< C<(FUN*)0xDEADFACE> >();

        runA();
    }
    __except(1)
    {
        printf("catastropha!\n");
    }
}


Фокус в том, что наш
Re[2]: детские грабли: declspec novtable
Здравствуйте, rus blood, Вы писали:

RB>If you attempt to instantiate a class marked with novtable and then access a class member, you will receive an access violation (AV).


Не AV, а любое другое UB.

#include <stdio.h>

struct __declspec(novtable) A
{
    A() { printf("%p A::ctor\n", this); }
    ~A() { printf("%p A::dtor\n", this); }

    virtual void foo() { printf("%p A::foo\n", this); }
    void bar() { A::foo(); }
    void buz() { foo(); }
};

struct B
{
    virtual void hello() { printf("%p B::hello\n", this); }
};

typedef int (*FUN)();
FUN pvfc_table[1] = { _purecall };

int surprize() { printf("surprize!\n"); return 0; }
FUN surprize_table[1] = { surprize };

template<FUN* table>
struct С
{
    С() : p(table) {}
    FUN* p;
};

void runA()
{
    A a;
    a.foo();
    a.bar();
    a.buz();
}

template<class T>
void runT()
{
    T t;
}

int main()
{
    __try
    {
        // выберите любой вариант
        runT< B >();
        runT< C<nullptr> >();
        runT< C<pvfc_table> >();
        runT< C<surprize_table> >();
        runT< C<(FUN*)0xDEADFACE> >();

        runA();
    }
    __except(1)
    {
        printf("catastropha!\n");
    }
}


Фокус в том, что наш объект A вообще не инициализирует vptr — и хватает любой мусор, лежавший там до конструирования.