| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > CodeGuard и выравнивание. |
| Автор: Riply 15.7.2008, 00:20 | ||
| Здравствуйте ! Не могу определить область в которой у меня "недопонимание" (С, Builder или Native, а может и все вместе Решила, что поместив в "для новичков" точно не ошибусь Имеем C++ Builder и следующую процедуру:
Все работает, пока мы не меняем настройки CodeGuard После включения опции "All CodeGuard options on" NtCreateFile выдает STATUS_DATATYPE_MISALIGNMENT (Invalid access to memory location) Nt - описание: // Alignment Fault // A datatype misalignment was detected in a load or store instruction. //...winnt #define STATUS_DATATYPE_MISALIGNMENT ((NTSTATUS)0x80000002L) Насколько я понимаю, требуется выравнивание на 32 битную границу. Но assert`ы не срабатывают. Значит передаем, вроде правильно... Соответственно, появляются два вопроса: Почему так происходит ? Как с этим бороться ? (Отключение CodeGuard`а считаю недостойным решением |
| Автор: ama_kid 15.7.2008, 07:14 |
| попробуй поиграться параметрами Data Aligment на вкладке "Advanced compile". Билдера под рукой нет, проверить не могу, но есть ощущение, что структуру OBJECT_ATTRIBUTES надо выравнивать как-то... |
| Автор: jonie 15.7.2008, 19:32 | ||
еще билдер вроде как поддерживает директиву #pragma
|
| Автор: Riply 16.7.2008, 02:22 | ||
| Докопалась до вот этого: В одном из юнитов (не в том где вызывается наша процедура) есть такие строчки:
Если их закоментировать, то проекту становиться глубоко чихать на настройки CodeGuard. Знай себе работает и не пискает Если же их "открыть", то работаем только с отключенным CodeGuard (ошибка описана выше). Объясните, пожалуйста, что крамольного в таком объявлении и как эта крамола влияет на работу ? |
| Автор: bsa 16.7.2008, 11:30 |
| Riply, ну если представить себя препроцессором и обработать эти строчки, то получится, что переменной NtDll_LibNameU присваивается набор значений, в частности, два числа и указатель на строку. А так как объявления UNICODE_STRING нет, то нельзя сделать вывод, что это за структура такая... |
| Автор: ama_kid 16.7.2008, 13:11 | ||||||||
|
| Автор: Riply 16.7.2008, 13:45 | ||
"сымитировать проблему" очень просто. Прежде чем утверждать, что влияют именно эти строчки, я попробовала исключить все возможные собственные ляпы следующим образом: 1. Создала новый пустой проект (WindowsFormApplication) C++Builder 2006 2. Нашла и скопировала в него код из http://forum.vingrad.ru/index.php?showtopic=180900&view=findpost&p=1310202 (некоторым он должен быть очень знаком 3. Добавила туда #include <winternl.h> и эти две строчки 4. Включила CodeGuard + в Tools->CodeGuard Configuration включила Append to log file Вот и все: наблюдаю этот эффект Это некузявый вариант. Хорошо что данная вещь проявилась с помощью CodeGuard. Где гарантии, что она не аукнется в другое время и в другом месте ? Ведь истинные причины и механизм сбоя я до сих пор понять не сумела Добавлено через 8 минут и 22 секунды Попробовала (хотя мне ой как далеко до него и с удивлением обнаружила, что ULONG(NtDll_LibNameU.Buffer) выражается аж нечетным числом. Сейчас пытаюсь понять: это я ничего не смыслю в указателях из С или данный дефайн, действительно никуда не годится |
| Автор: bsa 16.7.2008, 16:13 |
| Riply, то, что buffer выражается нечетным числом, это не криминал. Это же указатель. |
| Автор: Riply 16.7.2008, 18:32 | ||
"Как прикажешь тебя понимать, Саид ?" (с) Насколько, я понимаю, криминал да еще и какой Во всяком случае, ни одна из тех Nt-функций, на которых я проверяла, не переваривала "нечетный" Buffer в имени. (Хотя для забраковки метода достаточно, чтобы ругалась всего одна) Впрочем, это легко проверить, инициализировав UNICODE_STRING вручную и передав в любую понравившуюся Nt-ф-ию. Меня удивляет другое: то что мы получаем такой буфер этим "дефайном" и его влияние на "код в целом". |
| Автор: Riply 16.7.2008, 19:30 | ||
| Может кому интересно. Вот маленький отчет: Наш дефайн не виновен и полностью оправдан. Тяжким бременем обвинения ложатся либо на Builder, либо на CodeGuard Опыты показали следующее:
Данный вариант работает при любых настройках CodeGuard. Но стоит раскоментировать первую строчку (не трогая вторую), и при включенном CodeGuard получаем "нечетный" Buffer и нецензурщину от NtCreateFile. Причем не важно используем ли мы RTL_CONSTANT_STRING или расписываем его на месте вручную. Эффект тот же. Т.е. данный способ декларации так влияет на инициализацию TestFile, что не спасает даже последующая попытка использовать RtlInitUnicodeString. P.S. Понимаю, что меня сейчас растерзают на месте, но скажу: Delphi себе таких шуток не позволяет |
| Автор: bsa 16.7.2008, 21:29 | ||
| Riply, повторяю, нечетный указатель это не криминал. Если хочешь проверить, сделай:
|
| Автор: Riply 17.7.2008, 02:34 |
Sorry, это я плохо излагаю свои мысли. Я имела ввиду, что такая инициализация нашего Buffer`а, это криминал, как минимум, для нашего конкретного случая (аккуратно выражаясь), а скорее всего, это криминал для любой Nt-функции, принимающей на входе UNICODE_STRING. Вот осторожность этой фразы меня и удивляет. Ибо (при данном коде) я бы утверждала, что p будет нечетным, а buffer бутед выровнен на 32-битную границу, а под BDS 2006 и выше на 64-битную. (Извращенные настройки среды мы не рассматриваем |
| Автор: bsa 17.7.2008, 21:10 | ||
я стараюсь быть осторожным |
| Автор: Riply 18.7.2008, 02:37 | ||
Слава богу ! А то я уж испугалась, что данный код может возвращать "неровный" указатель Ну вот. После того, как мы выяснили с какими неприятностями мы можем столкнутся, встает несколько вопросов: Как объявлять константы типа UNICODE_STRING, чтобы они сами были выровнены как минимум на 32-х битную границу и чтобы Buffer был выровнен как минимум на 32-х битную границу. Причем, чтобы это не зависило от внешних факторов (типа включения/выключения CodeGuard) и не влияло не остальной код ? Второй вопрос: есть у меня некая струтура. Код привожу на Delphi, ибо изясняясь только на этом языке (пока еще) я могу быть уверена, что сказала именно то, что хотела сказать
Констант типа SysClassGuid_DiskDrive у меня как собак нерезанных Как, соблюдая условия, описанные для UNICODE_STRING, инициализировать их ? Причем сам _Guid должен быть выровнен как минимум на 64-х битную границу. И можно ли инициализировать константу GUID строкой, как в Delphi или мне вручную придется переводить строки типа '{4d36e967-e325-11ce-bfc1-08002be10318}' в числовые значения ? P.S. Я не стала выносить вопрос по инициализаци чистого GUID в отдельную ветку, т.к. он неразрывно связан с выравниванием. |
| Автор: bsa 18.7.2008, 11:28 |
| Если ты пишешь на билдере, то, думаю, там есть много функций одноименных аналогов дельфийских. |
| Автор: Riply 18.7.2008, 11:50 | ||
В том то и дело, что я еще настолько начинающая, что даже не определилась на чем писать Делаю так: пишу под Builder`ом, компилирую, проверяю корректность работы. Перехожу на VS 2005, компилирую тот же юнит, проверяю корректность работы. Если и там и там все в порядке, откладываю данный юнит как готовый у употреблению Поэтому привязки к Builder`ским ф-иям мне, к сожалению, не подходят |
| Автор: W4FhLF 18.7.2008, 12:23 |
| Системный софт для Windows лучше писать в средах от MS или по-крайней мере юзать хедеры и компилятор от MS. |
| Автор: Riply 18.7.2008, 12:52 | ||
До написания "системного софта" мне как до луны На данном этапе я учусь ствить "{" вместо "begin" Заодно пытаюсь нучиться правильно декларировать констаны, структуры и т.д. и т.п., ну и, разумеется, работать с ними. Как я поняла "сред от MS" много ? Какую из них лучше выбрать для изучения "с нуля" ? И где можо посмотреть(скачать) "хедеры от MS" ? |
| Автор: W4FhLF 18.7.2008, 13:05 | ||
Де-факто одна Если юзаешь студию 8-9, то для системного программирования там все зедеры есть. Для программирования дров надо качать спец. пакет WinDDK (бесплатно с сайта MS). Плюс сразу скачивай пакет Debuging Tools и символы(pdb). За подробностями сюда: http://www.microsoft.com/whdc/devtools/default.mspx + желательно иметь исходники винды, стянуть откуда-нибудь из торрентов, иногда туда полезно заглядывать. |
| Автор: Riply 18.7.2008, 13:15 | ||
Сейчас, у меня стоит VS 2005. Скачала 2008 с http://www.microsoft.com/express/download, но еще не ставила. Это то что нужно ? quote=W4FhLF, 18.7.2008, 13:05, post1584084]За подробностями сюда:[/quote] Спасибо.
Ну в том, что полезно заглядывать в исходники, меня убеждать не надо Правда, до этого, я лазила только в ReactOS. Есть что-то более близкое к оригиналу ? [ |
| Автор: W4FhLF 18.7.2008, 13:36 | ||
Если собираешься писать для висты включительно, то 2008 предпочтительнее просто из-за более новых хедеров и либ.
Ну я имел ввиду исходники Win NT4 и w2k, которые уплыли в сеть |
| Автор: Riply 18.7.2008, 15:35 |
| W4FhLF, спасибо. А с объявлением константы GUID, как я поняла, мне придется вручную переводить строку в числовые значения ? Перевести то не сложно, но теряется "наглядность" да и в MSDN GUID "описывается" строками. |
| Автор: W4FhLF 18.7.2008, 15:53 | ||
Функция http://msdn.microsoft.com/en-us/library/ms680589(VS.85).aspx сделает то, что тебе надо. Работает с т.н. OLESTR, которая по-существу является обычной Unicode строкой, поэтому передавай на вход UNICODE_STRING.Buffer. Про функции для работы с UNICODE_STRING читать либо в MSDN, либо DDK Help, либо http://www.osronline.com/DDKx/kmarch/k112_401e.htm. |
| Автор: Riply 18.7.2008, 16:34 | ||
Да эти ф-ии я знаю. Мне нужно декларировать константу. Что-то типа: const GUID MyGuid = {0, 1, 2, { 0, 1, 2, 3, 4, 5, 6, 7} }; Только хотелось вместо чисел использовать строку. В Delphi это возможно. Вот я и интересовалась, реализовано ли это в C ? |
| Автор: W4FhLF 18.7.2008, 16:59 | ||
Только если написать свой макрос, но я бы не стал заморачиваться. |
| Автор: bsa 18.7.2008, 17:07 | ||||
Угу. Вот оно:
|
| Автор: W4FhLF 18.7.2008, 17:11 | ||||||
bsa, ты ничего не путаешь?
Как это поможет из этого:
Получить структуру:
|
| Автор: Riply 18.7.2008, 17:30 |
Ну... "На нет и суда нет" Насчет "заморачиваться" подумаю. Этих констант много, лопатить их вручную лень. Опять же потеря наглядности и "совместимости" с MSDN. Есть еще один аргумент в пользу написания своего макроса: это поможет мне в обучении, если, конечно, получится |
| Автор: bsa 18.7.2008, 17:32 |
| вообще-то я показал, как именно подобное замутить на Си. Естественно, что реализация для GUID'а будет куда сложней. Хотя, если есть возможность отказаться от кавычек и дефисов, то можно вообще легко сделать. Если же нельзя, то придется огромный огород городить. |
| Автор: Riply 18.7.2008, 17:37 | ||
Я согласная (в смысле отказаться от "отказаться от кавычек" и уж если так необходимо, то и от дефисов). Но, не вижу как "можно вообще легко сделать" (пока). Натолкните на путь истинный |
| Автор: bsa 18.7.2008, 19:07 | ||
Как-то так (я с ## не очень работал, поэтому мог перепутать):
|
| Автор: Riply 19.7.2008, 07:43 | ||||
Спасибо. Не ожидала, что в C могут "проскакивать" подобные вещи Правда у меня среда ругается, говорит мол [C++ Warning] Main.cpp(122): W8056 Integer arithmetic overflow и так как я еще не разобралась, почему она не хочет так работать с Int64, решила попробовать сделать чуть по-другому. Вот что вышло: Первую ф-ию (RtlGUIDFromStringROs) я нагло сперла у ReactOS-евцев, чтобы наш "дефайн" не был "завязан" на NtDll (или на что-нибудь другое
Ну вот. Подготовка завершена, теперь попробуем определить наш "дефайн" и проверить его работоспособность:
Вроде получилось Буду очень признательна, за тыканье меня носом в ошибки, неувязки или просто в "так не делают" |
| Автор: Riply 21.7.2008, 06:20 | ||
| Если кому интересно: По первым тестам, данному "дефайну"
глубоко плевать на всякие там CodeGuard`ы вместе с их опциями - знай себе выдает "правильный" Buffer |