Tuesday, June 2, 2009

выстрелил тут себе в ногу.
у меня есть класс который конвертирует говно в специальное концентрированное говно.

class Compressor{
public:
Compressor();
int work(const char *src,char *dst);
private:
int uber_data;
int settings;
char *govnobuf;
};
Compressor *compressors = new Compressor[CPU_COUNT];

ну и они, экземпляры, там запускаются в разных потоках одновременно.
все работает, никаких вопросов.
и тут пришло время прикрутить второй вид концентратора SuperCompressor2.
полиморфизм и отделение интерфейса от реализации спасут нас, решил я и немедленно сделал так:

class AbstractCompressor
{
public:
virtual int work(const char *src,char *dst) = 0;
};

class Compressor: public AbstractCompressor{ ... };

class SuperCompressor2: public AbstractCompressor
{
public:
SuperCompressor2();
int work(const char *src,char *dst);
private:
int settings2;
char *govnobuf;
char *interimbuf;
};

ага.

AbstractCompressor *compressors;
if(application.settings.what_compressor_to_use)
compressor = new Compressor[CPU_COUNT];
else
compressor = new SuperCompressor2[CPU_COUNT];

очень круто. скомпилял, и внутренне радуясь своей сообразительности, запустил.
радость пропала ровно через двадцать секунд, когда программа упала с AV, при вызове

compressor[i].work(src,dst);

расстроился и вернул все обратно. почему? потому что при обращению к массиву компилятор вычисляет смещение исходя из определения оного, то есть получается

(AbstractCompressor *)((char *)compressor + i*sizeof(AbstractCompressor))

ежу понятно, что размеры у базового класса и унаследованного ниразу не обязаны совпадать. а массив, заметьте, выделен как массив дочерних классов. через это у меня случается стресс и депрессия, а у компилятора - говнокод.
спасибо.

1 comment:

vovs said...

Ну чо, с черема не пишется?