Страницы

Поиск по вопросам

суббота, 7 марта 2020 г.

Доступ к закрытому полю класса извне

#cpp #классы


Здравствуйте, нашел на неком ресурсе подобный код(немного его модифицировал под себя):

#include 

using namespace std;

class PrivateClass
{
public:
    PrivateClass(int a, char b)
        : privateInt(a), privateChar(b) {}
    int     getInt() {return privateInt; }
    char    getChar() {return privateChar; }
private:
    int     privateInt;
    char    privateChar;
};

class Stealer
{
public:

    int &stealInt(PrivateClass &clss)
    {
        return ((Stealer *) (&clss))->stealedInt;
    }

    char &stealChar(PrivateClass &clss)
    {
        return ((Stealer *) (&clss))->stealedChar;
    }

private:
    int     stealedInt;
    char    stealedChar;
};

int main()
{
    PrivateClass    prVar(20, 'a');
    Stealer         stVar;
    int &stlInt     = stVar.stealInt(prVar);
    char &stlChar   = stVar.stealChar(prVar);
    cout << "Private Class:\nInt = " << prVar.getInt() << "\nChar = " << prVar.getChar()
<< endl;

    cout << "\nStealed:\nInt = " << stlInt << "\nChar = " << stlChar << endl;
    stlInt  = -65;
    stlChar = 'q';
    cout << "Int = " << stlInt << "\nChar = " << stlChar << endl;
    cout << "\nPrivate Class:\nInt = " << prVar.getInt() << "\nChar = " << prVar.getChar()
<< endl;
    return 0;
}


Результат:

Private Class:
Int = 20
Char = a

Stealed:
Int = 20
Char = a
Int = -65
Char = q

Private Class:
Int = -65
Char = q


Как я понял, класс Stealer как-то получил доступ к закрытым полям класса PrivateClass
да ещё и по ссылке, что дало возможность менять значения переменной "извне". Увы, я
внятного ответа нигде не нашел. Что это может быть?
    


Ответы

Ответ 1



Тут все совершенно тривиально, что может и быть причиной того, что объяснения отсутствуют. Класс Stealer просто переинтерпретирует память объекта типа PrivateClass как память объекта типа Stealer. Расположение полей класса Stealer, согласно задумке, должно совпадать с расположением полей класса PrivateClass. Это означает, что, согласно задумке, после такой переинтерпретации, смотря через поля класса Stealer, мы будем "видеть" в памяти соответствующие поля класса PrivateClass. Подобные трюки нарушают требования strict aliasing языка C++. Код порождает неопределенное поведение и в общем случае неработоспособен. P.S. Прием, позволяющий легально обойти защиту, предоставляемую private я приводил вот здесь: https://ru.stackoverflow.com/a/656542/182825. В применении к данному случаю: http://coliru.stacked-crooked.com/a/49db7cfe2b1bc36b

Ответ 2



Грязный хак :) Просто сделан аналогичный по структуре класс, и область памяти, занятая одним классом, объявлена как область памяти, занятая другим классом, который позволяет обратиться к его данным, а уж открытые они там или закрытые... Класс не "получил доступ", он подменил объект другого класса собой. Вернее, даже не объект, а указатель на объект другого класса объявил, как указатель на объект своего класса - с такой же внутренней структурой. Грубо говоря, подделал паспорт :)

Комментариев нет:

Отправить комментарий