vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« : Март 13, 2007, 07:00:06 » |
|
Фрагмент программы: /* include */ #include "memory.h" #include "iostream.h"
/* test enum */ enum testEnum { value1, value2, value3, value4 };
/* test struct */ struct testStruct { testEnum te; unsigned char flag; };
/* main program */ int main(int argc, char* argv[]) { testStruct A, B; int st; ........... ........... A.te = value1; A.flag = 1; B.te = value1; B.flag = 1;
st = memcmp((void*)&A, (void*)&B, sizeof(A)); cout<<st<<endl; return 0; } /* end of program */ Результат выполнения программы: st = 1, т.е. А не равно B !!! Вопрос: Как такое может быть?
|
|
« Последнее редактирование: Март 19, 2007, 05:11:38 от vimmax »
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
Sochin
Злой модератор
Декан
Карма: +108/-6
Offline
Пол:
Сообщений: 1518
|
|
« Ответ #1 : Март 13, 2007, 09:05:15 » |
|
Вопрос: Как такое может быть?
Такое может быть если двоичное представление экземпляров структур в памяти неидентично. Например, при выравнивании членов в памяти могут образовываться дыры, заполненные мусором.
|
|
|
Записан
|
Говорят, когда компьютер сгорает, перед взором микропроцессора за долю секунды проносятся все операции, которые он когда-либо совершил... 壯鎭
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #2 : Март 14, 2007, 11:11:10 » |
|
В каком месте и сколько? конкретные цифры.
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #3 : Март 14, 2007, 05:15:01 » |
|
НУ? неужели никто не может посчитать?
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
Sochin
Злой модератор
Декан
Карма: +108/-6
Offline
Пол:
Сообщений: 1518
|
|
« Ответ #4 : Март 14, 2007, 05:42:18 » |
|
В каком месте и сколько? конкретные цифры.
Как в анеке: "Это уже второй сложный вопрос!". ))) Если серьезно, то 1) В каком месте: ясное дело, что между полями структуры, так как члены, объявленные рядом друг с другом, компилятор не обязательно расположит в памяти вплотную друг к другу. Вот читаем книжку: Размер объекта структурного типа не обязательно равен сумме размеров всех его членов. Это происходит по той причине, что на многих машинах требуется размещать объекты определенных типов, только выравнивая их по некоторой зависящей от системы адресации границе (или просто потому, что работа при таком выравнивании будет более эффективной ). Типичный пример - это выравнивание целого по словной границе. В результате выравнивания могут появиться "дырки" в структуре. 2) Сколько - это уже третий сложный вопрос. И вопрос не языка С++, а конкретной его реализации, т.е. ответ зависит от платформы и компилятора, а не от текста твоей программы или стандарта С++.
|
|
|
Записан
|
Говорят, когда компьютер сгорает, перед взором микропроцессора за долю секунды проносятся все операции, которые он когда-либо совершил... 壯鎭
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #5 : Март 15, 2007, 11:07:00 » |
|
Цитата правильная, но все таки.... В каком месте и сколько? конкретные цифры.
Для других структур показанный мной пример работает отлично и никогда никаких дыр не было!!!! И ничто не мешали сравнению структур по памяти. Но в этой структуре есть явная дыра. И ее необходимо увидеть.
На мой взгляд пример очень интересный...
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
Sochin
Злой модератор
Декан
Карма: +108/-6
Offline
Пол:
Сообщений: 1518
|
|
« Ответ #6 : Март 15, 2007, 11:26:04 » |
|
Цитата правильная, но все таки.... В каком месте и сколько? конкретные цифры.
Для других структур показанный мной пример работает отлично и никогда никаких дыр не было!!!! И ничто не мешали сравнению структур по памяти. Но в этой структуре есть явная дыра.
Явная-неявная...с точки зрения языка С++ нет никакой дыры. Дыры делает не язык, а компилятор. Еще раз: данный компилятор для конкретной плафтормы. Другой компилятор вполне может расположить иначе члены. С++ это не регламентирует и не ограничивает, насколько я понимаю.
|
|
|
Записан
|
Говорят, когда компьютер сгорает, перед взором микропроцессора за долю секунды проносятся все операции, которые он когда-либо совершил... 壯鎭
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #7 : Март 15, 2007, 11:56:54 » |
|
Sochin неправильно.
У кого нибудь есть еще варианты?
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
Sochin
Злой модератор
Декан
Карма: +108/-6
Offline
Пол:
Сообщений: 1518
|
|
« Ответ #8 : Март 15, 2007, 12:17:11 » |
|
Неправильно что?
|
|
|
Записан
|
Говорят, когда компьютер сгорает, перед взором микропроцессора за долю секунды проносятся все операции, которые он когда-либо совершил... 壯鎭
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #9 : Март 15, 2007, 12:30:04 » |
|
с точки зрения языка С++ нет никакой дыры - ДА Дыры делает не язык, а компилятор - Да С++ это не регламентирует и не ограничивает - неправильно, настраивает и ограничивает директивами препроцессора. Но для программиста это не отмазка. Программист должен знать какой код для его программы построит компилятор, ну я так считаю . У нас были случаи, когда приходилось бинарный код для контроллера открывать в дебаггере и смотреть асм код, т.к. на С все было написано без ошибок. Дыра есть )))) Лично я ее искал долго, 30 минут. А знающий человек подошел и сразу сказал где ошибка и точные цифры назвал. Я по дампу памяти сверил. Хотя можем об этом потом поспорить, когда ответ напечатаю, буду рад принять участие в споре
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
Sochin
Злой модератор
Декан
Карма: +108/-6
Offline
Пол:
Сообщений: 1518
|
|
« Ответ #10 : Март 15, 2007, 12:41:11 » |
|
С++ это не регламентирует и не ограничивает - неправильно, настраивает и ограничивает директивами препроцессора. Т.е. ты хочешь сказать, что стандарт С++ определяет некоторые директивы препроцессора, которые во всех реализациях языка для всех платформ позволяют четко задать в том числе и все параметры выравнивания членов структур в памяти? Я правильно тебя понял? Но для программиста это не отмазка. Программист должен знать какой код для его программы построит компилятор, ну я так считаю . У нас были случаи, когда приходилось бинарный код для контроллера открывать в дебаггере и смотреть асм код, т.к. на С все было написано без ошибок. Дыра есть )))) Лично я ее искал долго, 30 минут. А знающий человек подошел и сразу сказал где ошибка и точные цифры назвал. Я по дампу памяти сверил. Ты определись для начала где дыра. В С++, в твоей программе или в дампе памяти.
|
|
|
Записан
|
Говорят, когда компьютер сгорает, перед взором микропроцессора за долю секунды проносятся все операции, которые он когда-либо совершил... 壯鎭
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #11 : Март 15, 2007, 01:24:26 » |
|
1. Да. Только наверное стандарт ANSI C, мне кажется что стандарт C++ так и не принят, есть только вариации к нему. Или уже принят? Хотя со стандартами у меня слабовато. Но такая возможность есть.
2. Хихик, дыра в дампе памяти структуры, которая создана компилятором из программного кода. А в программе ошибка, неучитывающая этого.
3. Мне кажется тут кроме нас никого больше нету )))
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
Sochin
Злой модератор
Декан
Карма: +108/-6
Offline
Пол:
Сообщений: 1518
|
|
« Ответ #12 : Март 15, 2007, 02:34:57 » |
|
1. Да. Только наверное стандарт ANSI C, мне кажется что стандарт C++ так и не принят, есть только вариации к нему.
Стандарт С++ принят после долгих мучительных лет работы по стандартизации в 1998 году. Стандарт ISO/IEC 14882:1998 Programming Language C++. Имеется исправленная версия стандарта ISO/IEC 14882:2003 Programming Language C++. Стандартная библиотека языка С++ целиком включает в себя стандартную библиотеку языка С, описанную в стандарте ISO/IEC 9899:1990 Programming Language C. Рабочая группа по стандартизации С++ продолжает свою работу. Ссылочка на сайт ISOСсылочка на сайт международной рабочей группы по стадартизации С++Хотя со стандартами у меня слабовато.
А зря. "Стандарты надо читать!" (с) ( сами знаете какой самый-самый гуманнный преподаватель кафедры АСУ.) Было бы желание, в Сети можно бесплатно скачать последний доступный черновик стандарта. Окончательная версия правда платная. Но такая возможность есть.
В конкретной реализации (читай компиляторе) вполне возможно. В стандарте - врядли. Возможно разочарую, но скажу больше. Стандарт говорит вот о чем: представление, размер и диапазон фундаментальных типов зависит от реализации. У некоторых типов есть ограничения по выравниванию, которые также зависят от реализации. Стандарт определяет всего лишь минимальные требования для этих типов(см. файлы <climits> для целочисленных типов, <cfloat> для типов с плавающей точкой). В файле <limits> объявлены шаблоны для получения численнных характеристик всех фундаментальных типов. Круто, да? О каких конкретных цифрах может идти речь? )) 2. Хихик, дыра в дампе памяти структуры, которая создана компилятором из программного кода. А в программе ошибка, неучитывающая этого.
Ошибку в студию и тогда мы возможно подискутируем насколько это ошибка языка С++. 3. Мне кажется тут кроме нас никого больше нету )))
Ыыы. Есть еще космос и еще кое-что. )))
|
|
|
Записан
|
Говорят, когда компьютер сгорает, перед взором микропроцессора за долю секунды проносятся все операции, которые он когда-либо совершил... 壯鎭
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #13 : Март 15, 2007, 04:03:08 » |
|
Ок, так и быть, раз уж тут мы с тобой вдвоем и больше никого нет.
Вобщем директива #pragma pack(n) устанавливает границы выравнивания для структур, объединений и классов. По умолчанию n=8 хотя может принимать значения 1, 2, 4, 8 и 16.
Тут получается, что
sizeof(enum) = 4 байта. sizeof(unsigned char) = 1 байт.
sizeof(testStruct) = 8 байт ==> т.е. sizeof(enum) + sizeof(unsigned char) + 3 байта выравнивания до 8
| 1 2 3 4 | 5 | 6 7 8 | |**** **** **** **** | **** |**** **** **** | | enum | char | мусор | Вопрос номер два: какие строки необходимо добавить вместо "..........." чтобы структура А отличалась от В. Ответ: memset( (void*)&A, 0xff, sizeof(A)); memset( (void*)&B, 0xcc, sizeof(B));
PS спасибо за ссылки на стандарты.
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
Sochin
Злой модератор
Декан
Карма: +108/-6
Offline
Пол:
Сообщений: 1518
|
|
« Ответ #14 : Март 15, 2007, 06:17:58 » |
|
ОК, прагма так прагма. Читаем стандарт: 16.6 Pragma directive
A preprocessing directive of the form
# pragma pp-tokensopt new-line
causes the implementation to behave in an implementation-defined manner. The behavior might cause translation to fail or cause the translator or the resulting program to behave in a non-conforming manner. Any pragma that is not recognized by the implementation is ignored. Т.е. директива Pragma обрабатывается(и если обрабатывается, то как именно обрабатывается!) или не обрабатывается не зависит от твоей программы или от стандарта языка, а зависит только от реализации языка в конкретном компиляторе. Если конкретный компилятор не признает директиву #pragma pack(n), то он чихать на нее хотел и все равно выравняет члены как ему будет угодно. А если и признает, то не факт что будет выполнять именно выравнивание объектов, а может например отформатировать тебе винт. ))) И компилятор будет полностью прав, так как такое его поведение соответствует стандарту С++. )) Мораль? В этой задаче, если ты приводишь текст программы, а решение компиляторо-платформенно-зависимое, то необходимо указывать используемый компилятор/платформу. Я так думаю.
|
|
|
Записан
|
Говорят, когда компьютер сгорает, перед взором микропроцессора за долю секунды проносятся все операции, которые он когда-либо совершил... 壯鎭
|
|
|
Alder
|
|
« Ответ #15 : Март 15, 2007, 06:38:19 » |
|
Перечитал я все это и согласен с Sochin - решение задачи есть зависимым от компилятора.
|
|
|
Записан
|
"There are things known and there are things unknown, and in between are the doors..." (Jim Morrison)
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #16 : Март 15, 2007, 06:40:44 » |
|
уххххх..... ну чё я сказать могу? Твоя цитата относится ко всем директивам #pragma. А конкретно про #pragma pack ничего не сказано.Там только общие фразы и ничего конкретного.
я С реально использую и все мои задачи взяты реально из практики. Если исходить из твоей логики, тогда мой пример не имеет решения, и предопределить действие компилятора вообще невозможно? ерунда какая-то.
Что на практике проверено, то факт, а то что на бумаге написано - то фигня. Вот мое мнение.
Компиляторы: VC, gcc, Tornado, bc, STL для Siemens - все нормально поддерживают pragma pack и никто из них пока не возмущался. А эта директива используется чтобы выравнять размер структур при передаче данных от платформы к платформе, часто используется при передаче данных в сетях.
Единственная зависимость от компилятора и от платформы: установленное значение по умолчанию для #pragma pack
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #17 : Март 15, 2007, 06:45:16 » |
|
Если бы я сразу указал в начале программы #pragma pack(8 ) то все бы сразу поняли в чем дело. Это ж совсем не интересно ))))) А указать место мусора в структуре тоже было несложно.
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
Storm
Верховный
Администратор
Аспирант
Карма: +29/-0
Offline
Пол:
Сообщений: 484
|
|
« Ответ #18 : Март 15, 2007, 06:55:55 » |
|
а какой компилятор С ты используешь для какого процессора? Для тех процов, для которых пишу я на С,этот код даст ответ 0. ЗЫ: Потому что там выравнивание побайтовое и оперативки всего 512 байт
|
|
|
Записан
|
Только две вещи бесконечны: вселенная и тупость, и я еще не уверен по поводу вселенной. (Альберт Эйнштейн) ---------------------------------------------------- "There are two major products that came out of Berkeley: LSD and UNIX. We don't believe this to be a coincidence." (с) Jeremy S. Anderson
Проходит ирландец мимо паба....
|
|
|
vimmax
Модератор
Декан
Карма: +42/-3
Offline
Пол: Награды:
Сообщений: 1713
♪♪ ♫ ♪♪ ♫ ♪♪ ♫ ♪♪
|
|
« Ответ #19 : Март 15, 2007, 07:04:34 » |
|
Storm может и побайтовое, если контроллер. ))))))))) Вообще-то чтобы получилось 1 или -1, надо предварительно заполнить структуру (и мусор в ней) какими-то значениями, например командой memset. По стандарту в С++ все создаваемые объекты равны 0 или заполнены 0х00.
|
|
|
Записан
|
♪♪ ♫ LET FOREVER BE ♫ ♪♪ ♫ ♪♪ ♪♪ ♫
|
|
|
|