Re[4]: Вопрос на засыпку
От: Bell Россия  
Дата: 25.08.09 10:31
Оценка:
Здравствуйте, Кодт, Вы писали:

К>>ЧЯДНТ?


К>Я туплю, вот что я делаю не так.


Да уж, как говорится — не спешите выполнять приказание, возможно, что его еще отменят

В отладчике кстати видно, что значения указателей отличаются...
Любите книгу — источник знаний (с) М.Горький
Re[3]: Вопрос на засыпку
От: Bell Россия  
Дата: 25.08.09 10:49
Оценка:
Здравствуйте, remark, Вы писали:

R>Честно говоря, я немного затрудняюсь с ходу трактовать 4.10/2


Честно говоря, мне уже совсем не кажется, что дело в этом пункте.
Вернее даже так — дело совсем не в стандартном преобразовании к void*.
Любите книгу — источник знаний (с) М.Горький
Re[5]: Вопрос на засыпку
От: Кодт Россия  
Дата: 25.08.09 10:49
Оценка:
Здравствуйте, remark, Вы писали:

К>>Окей, тогда вот такой код


R>Занятный пример. Честно говоря, я не помню, что бы когда-либо сталкивался с adjustor служебной функцией.


Наверное, .asm-файлы редко смотрел и vftable не потрошил

R>Наверное adjustor всё равно эффективнее смещения this в месте вызова.


Для множественного перекрытия — это единственный выход (не считая извращений).
Поскольку Z::f перекрывает и X::f, и Y::f — она должна присутствовать в обеих таблицах.
Очевидно, что одно из этих присутствий опосредуется переходником, который корректно даункастит.

Вот если бы мы сделали
struct W { virtual void* e()=0; };
struct X { virtual void* f()=0; };
struct Y { virtual void* f()=0; };
struct Z : W, X, Y
{
    void* e() { return this; }
    void* f() { return this; }
    void* g() { return this; }
};

То вместо двух переходников (Z::X::f и Z::Y::f), кастящих к Z*, можно обойтись одним.

И действительно, Студия так и делает.
Z z;

z.e(); // кастинг Z->W тривиальный
z.f(); // кастинг Z->X (+4), в теле кастинг X->Z по месту (-4)
z.g(); // кастинг Z->Y (+8), в теле кастинг Y->Z по месту (-8)

Y& y = z; // Z->Y (+8)
y.f(); // в точке вызова кастинга нет, в переходнике кастинг Y->Z->X (-8+4 = -4), в теле кастинг X->Z по месту (-4)
y.g(); // в точке вызова кастинга нет, в теле кастинг Y->Z по месту (-8)
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[4]: Вопрос на засыпку
От: Кодт Россия  
Дата: 25.08.09 11:05
Оценка:
Здравствуйте, Bell, Вы писали:

R>>Честно говоря, я немного затрудняюсь с ходу трактовать 4.10/2


B>Честно говоря, мне уже совсем не кажется, что дело в этом пункте.

B>Вернее даже так — дело совсем не в стандартном преобразовании к void*.

В стандарте же не говорится, в каком виде this передавать. Конвенция thiscall — личное дело компилятора.
Вот захотел передавать на стеке и со смещением — ради бога.
Поскольку this — это значение, нигде официально не размещённое, то проверить его устройство мы не можем.

— Почему у твоей таксы такие короткие лапы?
— До земли достают, ну и достаточно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[3]: Вопрос на засыпку
От: Кодт Россия  
Дата: 25.08.09 11:05
Оценка:
Здравствуйте, remark, Вы писали:

R>Вообще изначально вопрос возник при разбирательстве, почему в следующем коде equal получается равным true. Это было бы логично, если бы статические типы this и other различались, ну там приведение между базовым и производным типами. А тут получается, что статические типы одинаковые, однако 2 физических не равных указателя при сравнении дают true.

R>
R>void T::f()
R>{
R>  T* other = ...;
R>  // assume this = 0x1000, and other = 0x2000
R>  bool equal = (this == other);
R>  ...
R>}
R>


Звучит как бред. Можешь привести рабочий пример, который валится на ассерте, хотя и не должен?
Или код и не должен валиться, но дебаггер при этом показывает ерунду?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[4]: Вопрос на засыпку
От: remark Россия http://www.1024cores.net/
Дата: 25.08.09 11:22
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Звучит как бред. Можешь привести рабочий пример, который валится на ассерте, хотя и не должен?

К>Или код и не должен валиться, но дебаггер при этом показывает ерунду?

Да, никакой код не валится. В итоге всё работает корректно. Я даже попытался дополнительно поломать код с помощью каких-то преобразований к void* и uintptr_t, но ничего не получилось. Пробовал делать типа такого:
uintptr_t p = (uintptr_t)this;
T* x = (T*)p;
assert(this == x);

Это работает как и ожидается, т.е. компилятор делает смещение при конвертации this к uintptr_t.

Однако дебаггер показывает различные адреса объектов, и в ассемблере они различны. Это и вызвано недоумение.
Кстати дебаггер корректно показывает содержимое объекта. Т.е. внутри X::foo() мы имеем this указывающий на другой объект Y, но дебаггер корректно показывает члены объект Х по такому указателю, т.е. он тоже неявно делает это смещение.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Вопрос на засыпку
От: Аноним  
Дата: 25.08.09 11:45
Оценка:
Здравствуйте, remark, Вы писали:

R>Я думаю, что через 5 минут после публикации вопроса нецелесообразно давать какие-либо подсказки, т.к. это будет нечестно по отношению к тем, кто хочет выдать свой ответ без каких-либо подсказок.


Миль пардоньте, не догнал, что это cup of coffee task.
Но вы сами виноваты, могли бы с множественным и виртуальным наследованием поиграться, да еще и не на ia32 платформе, чтобы уши указателя не торчали так явно
Re[4]: Вопрос на засыпку
От: remark Россия http://www.1024cores.net/
Дата: 25.08.09 11:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, remark, Вы писали:


R>>Я думаю, что через 5 минут после публикации вопроса нецелесообразно давать какие-либо подсказки, т.к. это будет нечестно по отношению к тем, кто хочет выдать свой ответ без каких-либо подсказок.


А>Миль пардоньте, не догнал, что это cup of coffee task.

А>Но вы сами виноваты, могли бы с множественным и виртуальным наследованием поиграться, да еще и не на ia32 платформе, чтобы уши указателя не торчали так явно


Тут идёт смещение не на размер указателя, а на размер объекта. Т.е. добавив здесь
Автор: remark
Дата: 25.08.09
в один из объектов большой массив, можно получить смещение сколь угодно большое. Соотв. сделав смещение 4, я как раз стремился запутать ситуацию, типа смещение идёт на размер какого-то указателя. Если бы смещение было, например, 1234h, то было бы очевидно, что идёт смещение на размер объекта, а это уже даёт какую-то информацию. У меня же смещение идёт на какие-то абстрактные 4... Ну хотя, что кому будет сложнее наверное субъективно. Кого-то бы может наоборот 1234h ввело бы в ступор...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.