Добро пожаловать! Это — архивная версия форумов на «Хакер.Ru». Она работает в режиме read-only.
 

Информативный заголовок: выделение памяти в C++

Пользователи, просматривающие топик: none

Зашли как: Guest
Все форумы >> [Компилируемые языки] >> Информативный заголовок: выделение памяти в C++
Имя
Сообщение << Старые топики   Новые топики >>
Информативный заголовок: выделение памяти в C++ - 2009-04-30 04:37:15.090000   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
задачка из области фокусов: ловкость рук и никакой магии

c.cpp:
... void C::size() { std::cout &lt;&lt; "sizeof *this = " &lt;&lt; sizeof(*this) &lt;&lt; std::endl; std::cout &lt;&lt; "located from " &lt;&lt; this &lt;&lt; " to " &lt;&lt; (this + 1) &lt;&lt; std::endl; } ...
main.cpp:
int main() { C obj; std::cout &lt;&lt; "sizeof obj = " &lt;&lt; sizeof(obj) &lt;&lt; std::endl; std::cout &lt;&lt; "located from " &lt;&lt; &obj &lt;&lt; " to " &lt;&lt; (&obj + 1) &lt;&lt; std::endl; obj.size(); return 0; }
вывод:
sizeof obj = 4
located from 0xbfb66eac to 0xbfb66ebc
sizeof *this = 8
located from 0xbfb66eac to 0xbfb66eec


вот так - несложным, в принципе, фокусом ломается система выделения памяти в C++: в данном случае для объекта размером в 8 байт было выделено 4 байта памяти, во время свёртки стека произойдёт ошибка сегментации

вопрос на подумать: как этого добиться? пряник и всеобщее признание тому, кто сможет получить подобный результат (различие во внешнем и внутреннем sizeof для объекта). дополнительный пряник тому, кто объяснит причину возникновения ошибки

лезьть в compiler internals запрещено, весь код должен быть в рамках ISO C++. описанный выше трюк одинаково хорошо работает с GCC и MSVS, не зависит от системы; может разрушить как стек, так и кучу. архитектура пусть будет фиксированная, x86. знание ассемблера для решения является крайне полезным, но не обязательным

N.B. существует по крайней мере два умеренно законных метода получить такое поведение компилятора
Post #: 1
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 10:24:41.846666   
rgo

Сообщений: 7170
Оценки: 281
Присоединился: 2004-09-25 05:14:25
причину я не объясню, но могу предположить. Все эти классы/структуры C++ помимо объявленных в них полей содержат всякую управляющую информацию, типа указателя на таблицу виртуальных функций. Причём никто не гарантирует, что &obj будет указывать на начало области выделенной под объект. Тот же указатель на vft может иметь адрес ((void**)&obj)[-1].
Что такое sizeof в C++, я честно говоря не знаю. Я читал стандарты про C – там всё прозрачно и соответствует интуиции. В C++ я боюсь в таких вещах полагаться на интуицию. Но если sizeof – это размер который занимает структура хранящая члены-переменные, а obj.size() – это размер выделенный из кучи, то это вполне всё объяснит. И мне кажется, что если хочется знать верный ответ на поставленный вопрос, то рыть надо именно в эту сторону.

ps. вот это:std::cout &lt;&lt; "located from " &lt;&lt; &obj &lt;&lt; " to " &lt;&lt; (&obj + sizeof(obj)) &lt;&lt; std::endl;Бред. Надо так:std::cout &lt;&lt; "located from " &lt;&lt; &obj &lt;&lt; " to " &lt;&lt; (&obj + 1) &lt;&lt; std::endl;
Post #: 2
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 11:46:55.153333   
Dgedit

Сообщений: 131
Оценки: 0
Присоединился: 2007-02-04 15:07:37.163333
Распиши польностью все исходники : я сделал вот так:
Post #: 3
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 11:50:38.473333   
Dgedit

Сообщений: 131
Оценки: 0
Присоединился: 2007-02-04 15:07:37.163333
Как вставит тут скрин? У меня ничего такого нету - все работает так как должно. И то что rgo сказал не влияет я пробовал и с виртуальными функциями и без них. Я компилировал в Visual Studio.
Post #: 4
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 12:20:18.766666   
SmanxX1

Сообщений: 208
Оценки: 0
Присоединился: 2007-07-31 14:33:56.650000
Denaturat
Залей куда-нибудь бинарник этой программки.

П.С. Вот для такого:
class C { public: void size() { printf("sizeof *this = %#2.2x\n",sizeof(*this)); printf("located from %#2.2x to %#2.2x\n", this, (this + sizeof(*this))); }; }; int main() { C obj; printf("sizeof obj = %#2.2x\n",sizeof(obj)); printf("located from %#2.2x to %#2.2x\n",&obj,(&obj + sizeof(obj))); obj.size(); return 0; } Результат:
sizeof obj = 0x01 located from 0x12ff7b to 0x12ff7c sizeof *this = 0x01 located from 0x12ff7b to 0x12ff7c
Post #: 5
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 14:49:26.233333   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: rgo

Что такое sizeof в C++, я честно говоря не знаю. Я читал стандарты про C – там всё прозрачно и соответствует интуиции. В C++ я боюсь в таких вещах полагаться на интуицию. Но если sizeof – это размер который занимает структура хранящая члены-переменные, а obj.size() – это размер выделенный из кучи, то это вполне всё объяснит. И мне кажется, что если хочется знать верный ответ на поставленный вопрос, то рыть надо именно в эту сторону.


и внутри и снаружи применяется один и тот же sizeof. каким бы он ни был, он один и тот же. а вот понять, как он работает в C++ - это существенно

quote:

ORIGINAL: rgo

ps. вот это:std::cout &lt;&lt; "located from " &lt;&lt; &obj &lt;&lt; " to " &lt;&lt; (&obj + sizeof(obj)) &lt;&lt; std::endl;Бред. Надо так:std::cout &lt;&lt; "located from " &lt;&lt; &obj &lt;&lt; " to " &lt;&lt; (&obj + 1) &lt;&lt; std::endl;


спасибо, опечатался. в варианте с единицей потерянные 4 байта хорошо видно:

sizeof obj = 4
located from 0xbffe5b3c to 0xbffe5b40
sizeof *this = 8
located from 0xbffe5b3c to 0xbffe5b44
Post #: 6
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 14:50:26.370000   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: Dgedit

У меня ничего такого нету - все работает так как должно. И то что rgo сказал не влияет я пробовал и с виртуальными функциями и без них. Я компилировал в Visual Studio.


так как должно каждый может :) задача именно в том, чтобы получить не как должно
Post #: 7
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 14:54:33.243333   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: SmanxX1

Denaturat
Залей куда-нибудь бинарник этой программки.


только если без него никто не решит

quote:

ORIGINAL: SmanxX1

П.С. Вот для такого…


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

ещё раз. задача - поломать этот механизм, получить средствами чистого ISO C++ нарисованный выше результат
Post #: 8
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 16:40:37.213333   
Dgedit

Сообщений: 131
Оценки: 0
Присоединился: 2007-02-04 15:07:37.163333
Ты тогда объясняй понятнее. Получается мы имеем черный ящик в виде объекта А. надо описать этот черный ящик так чтобы получить результат который ты вывел в примере?
Post #: 9
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 17:08:23.900000   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: Dgedit

Ты тогда объясняй понятнее. Получается мы имеем черный ящик в виде объекта А. надо описать этот черный ящик так чтобы получить результат который ты вывел в примере?


бинго!
Post #: 10
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 17:30:25.993333   
_SaZ_

Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
Ещё не все потеряно :D. Не копался, но имхо дело с vtable / наличием абстрактных методов.
Post #: 11
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 17:54:22.090000   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: _SaZ_

дело с vtable / наличием абстрактных методов.


ну тогда вопрос тебе лично: где расположен vtable в памяти?
Post #: 12
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 18:49:55.333333   
Dgedit

Сообщений: 131
Оценки: 0
Присоединился: 2007-02-04 15:07:37.163333
Адрес vtaable расположен в первых четырех байтах полиморфного объекта.
Post #: 13
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 19:30:23.840000   
SmanxX1

Сообщений: 208
Оценки: 0
Присоединился: 2007-07-31 14:33:56.650000
quote:

ещё раз. задача - поломать этот механизм, получить средствами чистого ISO C++ нарисованный выше результат

Ну так бы сразу и написал, а то
quote:

вот так - несложным, в принципе, фокусом ломается система выделения памяти в C++

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

По задаче. Нуу, ошибку сегментации можно получить разными способами, например разыменованием нулевого указателя.
Может как-нибудь с this поиграться, только вряд ли это даст нужный результат.
Post #: 14
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 19:33:00.326666   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: SmanxX1

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


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

quote:

ORIGINAL: SmanxX1

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


попробуй
Post #: 15
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 19:35:29.660000   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: Dgedit

Адрес vtaable расположен в первых четырех байтах


к задаче это не относится, но вот в этой фразе есть ошибка. выделенное - всегда ли?
Post #: 16
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 20:01:21.736666   
Dgedit

Сообщений: 131
Оценки: 0
Присоединился: 2007-02-04 15:07:37.163333
Ну я не встречал нигде описания случаев когд аэто может быть по другому. Возможно что в стандарте можно что-то такое выкопать необычное когда виртуальнаая таблица будет не в первых 4 байтах.
Если бывает так как ты говоришь то напиши пожалуйста будет интересно расширить кругозор
Post #: 17
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 20:15:36.500000   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
какой размер указателя на 16, 32 и 64-битных архитектурах?
Post #: 18
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 20:21:56.666666   
SmanxX1

Сообщений: 208
Оценки: 0
Присоединился: 2007-07-31 14:33:56.650000
-del (не то)
Post #: 19
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 20:28:09.776666   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
del :)
Post #: 20
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 22:22:25.770000   
kreol

Сообщений: 823
Оценки: 0
Присоединился: 2007-03-08 03:13:06.876666
Возможно, нужно рыть в сторону вот этих особенностей:
quote:

When the sizeof operator is applied to a class, struct, or union type, the result is the number of bytes in an object of that type, plus any padding added to align members on word boundaries. The result does not necessarily correspond to the size calculated by adding the storage requirements of the individual members.

quote:

If an unsized array is the last element of a structure, the sizeof operator returns the size of the structure without the array.

Хотя я больше склоняюсь к версии с vtable. В любом случае это нужно читать про выделение памяти для объектов и смотреть на смещения.
Post #: 21
RE: Информативный заголовок: выделение памяти в C++ - 2009-04-30 22:35:54.236666   
kreol

Сообщений: 823
Оценки: 0
Присоединился: 2007-03-08 03:13:06.876666
А ещё стоит обратить внимание на то, что sizeof - это оператор времени компиляции. Может быть, во время компиляции класса его размер другой, нежели во время компиляции  модуля, где объявляется объект данного класса? Но это уже нужно знать С++ лучше, чем его знаю я :)
Post #: 22
RE: Информативный заголовок: выделение памяти в C++ - 2009-05-01 00:38:58.096666   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: kreol

…во время компиляции класса его размер другой, нежели во время компиляции  модуля, где объявляется объект данного класса?


совершенно верно, вообще говоря. осталось это реализовать
Post #: 23
RE: Информативный заголовок: выделение памяти в C++ - 2009-05-04 12:57:34.303333   
rgo

Сообщений: 7170
Оценки: 281
Присоединился: 2004-09-25 05:14:25
что я делаю не так:[~]$ cat tmp.cc #include &lt;iostream&gt; class C { public: C (int n=0) : n (n) {} void size (); private: int n; }; void C::size() { std::cout &lt;&lt; "sizeof *this = " &lt;&lt; sizeof(*this) &lt;&lt; std::endl; std::cout &lt;&lt; "located from " &lt;&lt; this &lt;&lt; " to " &lt;&lt; (this + 1) &lt;&lt; std::endl; } int main () { C obj; std::cout &lt;&lt; "sizeof obj = " &lt;&lt; sizeof(obj) &lt;&lt; std::endl; std::cout &lt;&lt; "located from " &lt;&lt; &obj &lt;&lt; " to " &lt;&lt; (&obj + 1) &lt;&lt; std::endl; obj.size(); return 0; } [~]$ g++ tmp.cc [~]$ ./a.out sizeof obj = 4 located from 0xbf91b83c to 0xbf91b840 sizeof *this = 4 located from 0xbf91b83c to 0xbf91b840 [~]$
+++
попробовал разбить это на два файла, и потом линковать объектники… результаты отличаются цифрами, но "чёрного ящика" я не вижу…
ps. ах да. gcc версии 4.1.2
pps. на домашнем компьютере, то же самое, с точностью до незначительных деталей:[rgo tmp]$ ./a.out sizeof obj = 4 located from 0x7fff8f5f1630 to 0x7fff8f5f1634 sizeof *this = 4 located from 0x7fff8f5f1630 to 0x7fff8f5f1634
Post #: 24
RE: Информативный заголовок: выделение памяти в C++ - 2009-05-04 16:37:06.230000   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
quote:

ORIGINAL: rgo

что я делаю не так


ты всё делаешь правильно - как и предполагают компилятор/линкер,- потому и результат вполне ожидаемый

для того, чтобы получить описанную выше ошибку, их надо обмануть. для этого достаточно добавить одну строчку и один файл, либо строчек пять-шесть в существующих файлах
Post #: 25
RE: Информативный заголовок: выделение памяти в C++ - 2009-05-07 15:41:58.580000   
Denaturat

Сообщений: 1741
Оценки: 453
Присоединился: 2008-10-27 20:50:06.380000
скучно как-то. идеи закончились?
Post #: 26
Страниц:  [1]
Все форумы >> [Компилируемые языки] >> Информативный заголовок: выделение памяти в C++







Связаться:
Вопросы по сайту / xakep@glc.ru

Предупреждение: использование полученных знаний в противозаконных целях преследуется по закону.