Виртуальные функции - зло?
- Войдите на сайт для отправки комментариев
Преветствую форумчан! Сегодня столкнулся с совершенно невероятным непонятным нечто. В общем - убиваются данные в памяти. И так крутил и этак, пока не понял, что всё очень плохо. И так, постановка:
Имеем класс А и класс B. Создаем в рантайме (через new) соответствуюзие экземпляры. В классе А виртуальные функции отсутствуют, но в нем выделяется буфер. В классе B присутствует виртуальная функция, которая вызывается. Друг о друге классы пока что не подозревают. Но, как только вызывается виртуальная функция 'экземпляра B, в которой происходит инициализация двух переменных, начинает портиться буфер экземпляра А. Продебажил указатели и вижу:
buffer а(А) ptr: 871
ptr to object b(B): 867
sizeof(B): 5
т.е. получается "нахлест" в один байт! как такое может быть? это же просто эпичный фейл. тепеь фокус - убираем идентификатор виртуальности и размер становится уже 3, при тех же адресах.
Магия? Бубен? Куда бы постучать?
PS:
Atmel Studio 7 (Version: 7.0.1188 - ) Arduino IDE for Atmel Studio 7 Version: 1609.4.3
Да, почему "зло"? Вполне себе добро, если "готовить уметь".
Про пример ничего не скажу, т.к. его не видел.
У меня машина издает странные звуки, шир-шир, хра-хра, скажите, что с ней не так?
Думал что доступно описал проблему. Прошу прощение за невежество :) И так, имеем основной ino-файл
#include "FastDisplay/FastDisplay.h" #include "BaseFontClass.h" FastDisplay * myFastDisplay; BaseFontClass * baseFont; void setup() { Serial.begin(921600); myFastDisplay = new FastDisplay(); baseFont = new BaseFontClass(); //Serial.println("lets start"); myFastDisplay->init( 8, 4 ); //Serial.println("end..."); baseFont->init(); Serial.println("+++"); }Далее заголовочный файл FastDisplay.h, который был условно обозначен "А"
class FastDisplay { private: int CS; int devicesCount; byte * hiddenScreen; protected: public: FastDisplay(); void init(int cs, int devices); };Ему соответствует cpp
FastDisplay::FastDisplay() { //currentFont = NULL; } void FastDisplay::init(int cs, int devices) { CS = cs; devicesCount = devices; hiddenScreen = new byte[devices*8]; Serial.println("--"); Serial.print("a(A) ptr: "); Serial.println((int)this); Serial.print("sizeof(A): "); Serial.println(sizeof(FastDisplay)); Serial.print("a(A) buffer ptr: "); Serial.println((int)hiddenScreen); }Заголовок условного класса "B"
struct Symbol { byte sim; byte width; byte data[8]; }; class BaseFontClass { private: Symbol * sims; byte count; public: BaseFontClass(); virtual void init(); };cpp к нему
BaseFontClass::BaseFontClass() { sims = NULL; count = 0; } void BaseFontClass::init() { Serial.print("b(B) ptr: ");Serial.println((int)this); Serial.print("sizeof(B): ");Serial.println(sizeof(BaseFontClass)); //this->sims = NULL; //this->count = 2; }Вот такие не хитрые исходники. Берем теперь это добро и запускаем:
--
a(A) ptr: 738
sizeof(A): 6
a(A) buffer ptr: 750
b(B) ptr: 746
sizeof(B): 5
+++
указатель на только что созданный буфер указывает на последний байт объекта "b". Делаем магию, убираем virtual
--
a(A) ptr: 738
sizeof(A): 6
a(A) buffer ptr: 750
b(B) ptr: 746
sizeof(B): 3
+++
И количество wtf в час переваливает все разумные пределы.
Подописывал инклуды, собрал, залил в Нану. Выдало
Serial.begin(921600);выдает в Вас любителя скорости и экстрима... Вы компилятор дорабатывали, ну чтоб быстрей было?Подописывал инклуды, собрал, залил в Нану.