Причем, из того, что второй фрагмент well-formed, отнюдь не следует, что первый также well-formed, поскольку никто не гарантирует равенства указателей obj1 и obj2.
--
Справедливость выше закона. А человечность выше справедливости.
CS>>Какая конкретно строка здесь вызывает сомнения?
R>Строка, помеченная жирным, согласно 3.8.1 порождает неопределенное поведение. Об уже этом говорил zaufi здесь
R>Причем, из того, что второй фрагмент well-formed, отнюдь не следует, что первый также well-formed, поскольку никто не гарантирует равенства указателей obj1 и obj2.
Тут дело не в численном равенстве указателей, они могут быть равны, дело в типизации, в том, что компилятор знает, что obj указывает на Base, и может этим знанием пользоватсья, потому что не предполагается, что тип вдруг изменится — это против правил статически типизированного С++. Например, он возьмет адрес из указателя на vtbl при первом обращении и закеширует его в регистр и дальше все вызовы направит непосредственно в нее, минуя указатель на vptr в объекте. Соответственно он изменения указателя на vptr попроcту не заметит.
А когда у нас есть obj2, компилятор либо видит, откуда он пришел, и ставит соответствующий тип статически (девиртуализация), либо, если функция подмены скрыта в бибилотеке, он просто относится к нему как к новому указателю и должен честно пойти в объект и взять указатель на vptr оттуда (после чего он имеет полное право опять его закешировать и т.д.)
CS>>Какая конкретно строка здесь вызывает сомнения?
R>Строка, помеченная жирным, согласно 3.8.1 порождает неопределенное поведение. Об уже этом говорил zaufi здесь
CS>Какая конкретно строка здесь вызывает сомнения?
Конкретно тут 2 помеченные
В //!!! 1 нет гарантий, что размеры объектов совпадают. Если они есть, по покажикто и как гарантирует это. Но это можно заткнуть при помощи static_assert, например...
В //!!! 2 нет гарантий, что значение выражения static_cast<Base*>( new(memory) Particular() ) совпадёт с obj...
Кроме того, мне не нравятся пустые скобки после имён типов в new.
Но сомневался я в другом.
E>>Что-то сильно я сомневаюсь, что можно так вольно обращаться с полями. В конце концов, например, деструктор класса позовёт деструктор поля, а там уже совсем и не то...
CS>На чем основаны твои сомнения?
Тут где-то был примерно такой код:
class struct {
Base Agg;
void Ups() {
new(&agg) Particular; // IMHO, так точно нехорошо делать...
}
};
И нехорошо по многим причинам сразу.
Во-первых, компилятор может что-то такое сделать в деструкторе, чего нам не понравится
Во-вторых, в пользовательском коде компилятор может быть уверен, что тип поля это Base, и не станет прибегать к виртуальным вызовам вовсе...
Так что нехорошо это всё. И главное, совершенно не понятно ради чего.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, c-smile, Вы писали:
CS>Хотел бы я посмотреть на компилятор делающий "девиртуализацию" COM или Corba интерфейсов которые есть сугубо abstract classes. CS>COM и Corba интерфейсы имеют форму понимаемую и C++ и C. Т.е. всегда возможно получить доступ к vtbl полю. Хотя бы зайдя через C.
Ну посмотри на gcc и MSVC, например...
Скажем в коде
struct Base { virtual ostream& F() { return std::cout << "Base"; } };
extern void magic_gop_swap( base* ); // тут может сидеть наш хак...struct Dir : Base { virtual ostream& F() { return std::cout << "Dir"; } };
void test_it()
{
Base& b = *new Dir;
b.F() << std::endl;
magic_gop_swap( &b )
b.F() << std::endl;
delete &b;
}
любой из этих компиляторов может, и имеет право, дооптимизироваться до кода эквивалентного такому:
CS>placement new C++ для замены vtbl это конечно не тот кунштюк который рекомендован для использования детям дошкольного возраста. CS>Просто надо знать что есть такая фича и она работает by C++ nature. Но использовать надо осознанно и по делу. Как всегда в C++ впрочем.
Есть мнение, что единственным делом, по которому это надо использовать осознанно является диверсия...
CS>На войне как на войне.
Зачем же жить "как на войне"? Может лучше НОРМАЛЬНУЮ архитектуру залудить в программе, чтобы хаки не требовались?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>Причем, из того, что второй фрагмент well-formed, отнюдь не следует, что первый также well-formed, поскольку никто не гарантирует равенства указателей obj1 и obj2.
К сожалению, даже и при равенстве не будет грантии работоспособности. Только при отключенном/отсутствующем оптимизаторе...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
CS>void* a = new(memory) Base();
CS>void* b = new(memory) Particular();
CS>
CS>может приводить к false этого условия
CS>
CS>(void*)a == (void*)b
CS>
Нам это условие не нужно. Нам нужно равенство указателей на Base...
А причин может быть сколько угодно. Например ОС может поддерживать, в целях безопасности, такую модель памяти, что ни при каких двух аллокациях не получается двух равных указателей...
CS>На самом деле если (void*)a != (void*)b это значит что CS>
CS>sizeof Base != sizeof Particular
CS>
Это тоже хорошо бы доказать... Например, в лэйауте базы могут быть дыры, которые как-то использует наследник...
CS>я желаю услышать также причины при которых это возможно. Классы я описал выше.
А можно чуть-чуть другие классы? А то классы выше вообще не нужны. Вместо них намного проще юзать указатели на функции...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Во-первых, это всё вообще никак не связано с предыдущим.
Во-вторых, в С++ полимрфных векторов не бывает. Либо виртуализация, либо масив объектов. Сразу и то и то нельзя. Ну в смысле можно, конечно, но ССЗБ.
В частности, операция + для указателя и целого валидна только для указателей ВНУТРЬ ВЕКТОРА. Для указателей на одинокие объекты это UB... Вернее неспецифицированное, как мне кажется...
CS>А как же begin() и end() итераторы например?
А в чём там проблемы?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
E>Здравствуйте, c-smile, Вы писали:
Z>>>это хак в любом случае, в зависимости от того документированный он или нет можно только подставлять разные эпитеты... типа "грязный хак", например CS>>Я знаю use cases где это решение приносит значительный профит.
E>Поподробнее не расскажешь?
^^^^^^^^^^^^ SUBJ ^^^^^^^^^^^^
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, rg45, Вы писали:
R>>Причем, из того, что второй фрагмент well-formed, отнюдь не следует, что первый также well-formed, поскольку никто не гарантирует равенства указателей obj1 и obj2.
E>К сожалению, даже и при равенстве не будет грантии работоспособности. Только при отключенном/отсутствующем оптимизаторе...
Это да. Я просто проблему, что называется, "беру по частям".
--
Справедливость выше закона. А человечность выше справедливости.
Хаком тут является отсутствие вызова деструктора и отсутствие проверки необходимого размера. Все. Для рассказывающих ужастики повторяю: ВСЕ.
ЗЫ зря ты топик назвал 'замена VPTR' — это создает ощущение жуткого батхерта, которое и стараются передать многочисленные ужасающиеся в этом топике. Надо называть вещи своими именами — placement new на своей "куче".
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
O>Хаком тут является отсутствие вызова деструктора и отсутствие проверки необходимого размера. Все.
Это-то, как раз, фигня, потому что легко чинится.
Суть хака в том, что мы используем всё тот же указатель...
И вот это неизлечимо. А без этого хака вообще нет повода для страданий. Можно не страдать со всеми этими тонкостями, а просто иметь пул объектов и брать из пула нужный.
Тем более, что объекты без полей, так что можно иметь по статической копии каждого типа и всё...
Повторяю: ВСЁ
O>ЗЫ зря ты топик назвал 'замена VPTR' — это создает ощущение жуткого батхерта, которое и стараются передать многочисленные ужасающиеся в этом топике. Надо называть вещи своими именами — placement new на своей "куче".
Ой, а разве это "своими именами"? IMHO, в зависимости от версии обсуждаемого кода, надо или "..на чужой куче" или "...в storage другого поля". Только конретно эти стороны этого хака не важны, к сожалению... O>Для рассказывающих ужастики повторяю: ВСЕ.
А ещё крупнее слабо написать?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, ononim, Вы писали:
O>Хаком тут является отсутствие вызова деструктора и отсутствие проверки необходимого размера. Все. Для рассказывающих ужастики повторяю: ВСЕ. O>ЗЫ зря ты топик назвал 'замена VPTR' — это создает ощущение жуткого батхерта, которое и стараются передать многочисленные ужасающиеся в этом топике. Надо называть вещи своими именами — placement new на своей "куче".
+1
Флейм также отчасти спровоцирован тем, что исходный пример содержит ошибку. Участники обсуждения тем или иным образом мысленно исправляют эту ошибку и делают это по-разному. Так возникла дискуссия между мной и k.o. — здесь
O>>Хаком тут является отсутствие вызова деструктора и отсутствие проверки необходимого размера. Все. E>Это-то, как раз, фигня, потому что легко чинится. E>Суть хака в том, что мы используем всё тот же указатель...
И что? Все кучи (включая встроенную студийну) работают на "реюзании указателей". Признакомом убивания объекта для любого супероптимизирующего компилятора должен быть вызов деструктора. Которого действительно в коде топикстартера нету, но это не design flaw.
E>Тем более, что объекты без полей, так что можно иметь по статической копии каждого типа и всё... E>
Повторяю: ВСЁ
O>>ЗЫ зря ты топик назвал 'замена VPTR' — это создает ощущение жуткого батхерта, которое и стараются передать многочисленные ужасающиеся в этом топике. Надо называть вещи своими именами — placement new на своей "куче". E>Ой, а разве это "своими именами"? IMHO, в зависимости от версии обсуждаемого кода, надо или "..на чужой куче" или "...в storage другого поля". Только конретно эти стороны этого хака не важны, к сожалению...
Своими. new (p) OBJECT (args) — это Placement new. Фича языка про которую тут писали. Указатель p — это по сути свой буфер, для которого ты ручками (читай — своим аллокатором выделяешь память. Потому по сути то что сделал ТС это именно placement new и свой аллокатор. С двумя багами о которых я выше написал.
O>>Для рассказывающих ужастики повторяю: ВСЕ. E>А ещё крупнее слабо написать?
Запросто. ВСЕ
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
E>>Суть хака в том, что мы используем всё тот же указатель... O>И что? Все кучи (включая встроенную студийну) работают на "реюзании указателей".
Беда в том, что они работают не как угодно. а на основании довольно сложных правил, описанных, например, в стандарте С++...
O>Признакомом убивания объекта для любого супероптимизирующего компилятора должен быть вызов деструктора. Которого действительно в коде топикстартера нету, но это не design flaw.
Ну а все девушки должны тебе давать. Беда в том, что они хоть по твоему и должны, но всё же не делают этого...
Да, и кстати, если должны, то ты наверное можешь показать документ, эту обязанность устанавливающий?
O>Своими. new (p) OBJECT (args) — это Placement new. Фича языка про которую тут писали. Указатель p — это по сути свой буфер, для которого ты ручками (читай — своим аллокатором выделяешь память. Потому по сути то что сделал ТС это именно placement new и свой аллокатор. С двумя багами о которых я выше написал.
1) про placement new я и не спорил и не спорю. Просто ... короче писать.
2) Про аллокатор не согласен, но главное тут не в аллокаторе.
3) Суть хака НЕ В ТОМ. Суть вот в чём. Пусть у меня есть какая-то иерархия, из экземпляров её классов собрана какая-то сложная структура данных. Ну, например, дерево, какое-то или окошки GUI'я, например.
И вот я хочу чуть подправить поведение одного из узлов этой иерархии, ничего не пересвязывая и не пересоздавая...
Вот тут на сцену обсуждаемый хак и выходит...
O>>>Для рассказывающих ужастики повторяю: ВСЕ. E>>А ещё крупнее слабо написать? O>Запросто. ВСЕ
А У МЕНЯ ДЛИНЬШЕ И ТОЛЩЕ!!!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>Флейм также отчасти спровоцирован тем, что исходный пример содержит ошибку. Участники обсуждения тем или иным образом мысленно исправляют эту ошибку и делают это по-разному. Так возникла дискуссия между мной и k.o. — здесь
в ходе которой выявилась различная трактовка исходного примера.
Прикольно. А какие ещё трактовки есть?
Я так понял ТС, что он хотел бы сохранив старый указатель на базу, заиметь по этому адресу объект с модифицированным поведением. IMHO, это всё там довольно прозрачно восстанавливается.
А если придумать какой-то совсем другой вопрос где тоже есть new размещения, то можно много чего наобсуждать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, k.o., Вы писали:
KO>можно черновик C++0x посмотреть, там, это почти не изменилось: здесь, тоже 12.4/4.
Спасибо за идею.
Тут смотри что пишут:
A destructor is trivial if it is neither user-provided nor deleted and if: — the destructor is not virtual,
— all of the direct base classes of its class have trivial destructors, and
— for all of the non-static data members of its class that are of class type (or array thereof), each such
class has a trivial destructor.
Otherwise, the destructor is non-trivial.
требование снижено до отсутствия виртуальности самого деструктора, по сравнению с тем, что я помню.
Интересно, как оно было раньше?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском