Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> CodeGuard и выравнивание. 
V
    Опции темы
Riply
Дата 15.7.2008, 00:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Здравствуйте !
Не могу определить область в которой у меня "недопонимание" (С,  Builder или Native, а  может и все вместе smile. 
Решила, что поместив в "для новичков" точно не ошибусь smile
Имеем C++ Builder и следующую процедуру:
Код

NTSTATUS TLockFileNt::_DirectCreateFile
            (const PUNICODE_STRING pObjName, const ACCESS_MASK DesAccess, const PIO_STATUS_BLOCK pIoBlock, const ULONG FileAttr,
             const ULONG ShareAccess, const ULONG CreateDispos, const ULONG CreateOptions, const PHANDLE pRootDir)
{
  OBJECT_ATTRIBUTES ObjAttr;
  if (pRootDir)
    InitializeObjectAttributes(&ObjAttr, pObjName, OBJ_CASE_INSENSITIVE, *pRootDir, NULL);
    else InitializeObjectAttributes(&ObjAttr, pObjName, OBJ_CASE_INSENSITIVE, 0, NULL);
  assert(((ULONG)(&ObjAttr) & PRED_32) == 0);
  assert(((ULONG)(pObjName) & PRED_32) == 0);
  NTSTATUS RetStatus = NtCreateFile(&FFileHandle, DesAccess, &ObjAttr, pIoBlock, NULL,
                          FileAttr, ShareAccess, CreateDispos, CreateOptions, NULL, 0);
  if (! NT_SUCCESS(RetStatus)) FFileHandle = 0;
  return RetStatus;
};

Все работает, пока мы не меняем настройки 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`а считаю недостойным решением smile

PM MAIL   Вверх
ama_kid
Дата 15.7.2008, 07:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: нет
Всего: 95



попробуй поиграться параметрами Data Aligment на вкладке "Advanced compile". Билдера под рукой нет, проверить не могу, но есть ощущение, что структуру OBJECT_ATTRIBUTES надо выравнивать как-то...  smile 


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Riply
Дата 15.7.2008, 08:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Цитата(ama_kid @  15.7.2008,  07:14 Найти цитируемый пост)
попробуй поиграться параметрами Data Aligment на вкладке "Advanced compile". 


Ух ты, какая полезная "вкладка" smile
Но она не помогла  smile 
Я еще пока плаваю во всяких директивах компилятору.
Может быть такое, что с ними я напартачила в одном юните, а аукается это в другом ?
PM MAIL   Вверх
jonie
Дата 15.7.2008, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



еще билдер вроде как поддерживает директиву #pragma
Код
#pragma pack(push)
#pragma pack(1)
typedef struct{...}blablabla;
#pragma pack(pop)



--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Riply
Дата 16.7.2008, 02:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Докопалась до вот этого:
В одном из юнитов (не в том где вызывается наша процедура) есть такие строчки:
Код

#define RTL_CONSTANT_STRING(s)  { sizeof(s)-sizeof((s)[0]), sizeof(s), s }

const UNICODE_STRING NtDll_LibNameU = RTL_CONSTANT_STRING(L"ntdll.dll");


Если их закоментировать, то проекту становиться глубоко чихать на настройки CodeGuard.
Знай себе работает и не пискает smile
Если же их "открыть", то работаем только с отключенным CodeGuard (ошибка описана выше).

Объясните, пожалуйста, что крамольного в таком объявлении
и как эта крамола влияет на работу ?
PM MAIL   Вверх
bsa
Дата 16.7.2008, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Riply, ну если представить себя препроцессором и обработать эти строчки, то получится, что переменной NtDll_LibNameU присваивается набор значений, в частности, два числа и указатель на строку. А так как объявления UNICODE_STRING нет, то нельзя сделать вывод, что это за структура такая...
PM   Вверх
ama_kid
Дата 16.7.2008, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: нет
Всего: 95



Цитата(bsa @  16.7.2008,  11:30 Найти цитируемый пост)
А так как объявления UNICODE_STRING нет, то нельзя сделать вывод, что это за структура такая... 
В принципе, это штатная DDK-шная структура для работы с юникодными функциями
Код
typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING;
Другое дело, что сложно представить где объявление, используемое даже для написания драйверов kernel-mode, может аукнуться в обычном приложении.  smile
Цитата(Riply @  16.7.2008,  02:22 Найти цитируемый пост)
Объясните, пожалуйста, что крамольного в таком объявлении
и как эта крамола влияет на работу ?
Как влияет - ты уже выснила smile Крамольного, в принципе, ничего не вижу, но к примеру, где-нить может стоять директива типа такой:
Код
#ifdef RTL_CONSTANT_STRING 
...
#else
...
#endif
в которой CodeGuard в зависимости от этой декларации использует разные вызовы... Ввиду того, что неизвестно, какие хедеры\либы ты в своем проекте подключала, а самому сымитировать проблему не получилось, предположить что-либо более правдоподобное сложно smile


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Riply
Дата 16.7.2008, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Цитата(ama_kid @  16.7.2008,  13:11 Найти цитируемый пост)
Ввиду того, что неизвестно, какие хедеры\либы ты в своем проекте подключала, а самому сымитировать проблему не получилось, предположить что-либо более правдоподобное сложно 


"сымитировать проблему" очень просто.
Прежде чем утверждать, что влияют именно эти строчки, я попробовала исключить 
все возможные собственные ляпы следующим образом:
1. Создала новый пустой проект (WindowsFormApplication) C++Builder 2006
2. Нашла и скопировала в него код из http://forum.vingrad.ru/index.php?showtopic=180900&view=findpost&p=1310202
    (некоторым он должен быть очень знаком  smile )
3. Добавила туда #include <winternl.h> и эти две строчки
4. Включила CodeGuard + в Tools->CodeGuard Configuration включила Append to log file

Вот и все: наблюдаю этот эффект  smile 

Цитата(ama_kid @  16.7.2008,  13:11 Найти цитируемый пост)
где-нить может стоять директива типа такой:

Это некузявый вариант. Хорошо что данная вещь проявилась с помощью CodeGuard.
Где гарантии, что она не аукнется в другое время и в другом месте ?
Ведь истинные причины и механизм сбоя я до сих пор понять не сумела  smile

Добавлено через 8 минут и 22 секунды
Цитата(bsa @  16.7.2008,  11:30 Найти цитируемый пост)
Riply, ну если представить себя препроцессором


Попробовала (хотя мне ой как далеко до него  smile )
и с удивлением обнаружила, что ULONG(NtDll_LibNameU.Buffer) выражается аж нечетным числом.
Сейчас пытаюсь понять: это я ничего не смыслю в указателях из С или данный дефайн,
действительно никуда не годится smile

PM MAIL   Вверх
bsa
Дата 16.7.2008, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Riply, то, что buffer выражается нечетным числом, это не криминал. Это же указатель.
PM   Вверх
Riply
Дата 16.7.2008, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Цитата(bsa @  16.7.2008,  16:13 Найти цитируемый пост)
Riply, то, что buffer выражается нечетным числом, это не криминал. Это же указатель. 



"Как прикажешь тебя понимать, Саид ?" (с)
Насколько, я понимаю, криминал да еще и какой smile
Во всяком случае, ни одна из тех Nt-функций, на которых я проверяла, 
не переваривала "нечетный" Buffer в имени. (Хотя для забраковки метода достаточно, чтобы ругалась всего одна)
Впрочем, это легко проверить, инициализировав UNICODE_STRING вручную и передав в любую понравившуюся Nt-ф-ию.
Меня удивляет другое: то что мы получаем такой буфер этим "дефайном" и его влияние на "код в целом".


PM MAIL   Вверх
Riply
Дата 16.7.2008, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Может кому интересно. Вот маленький отчет:
Наш дефайн не виновен и полностью оправдан.
Тяжким бременем обвинения ложатся либо на Builder, либо на CodeGuard   smile 
Опыты показали следующее:
Код

UNICODE_STRING TestFile;// = RTL_CONSTANT_STRING(L"\\??\\E:\\Delete Files\\TestFile.txt");
RtlInitUnicodeString(&TestFile, L"\\??\\E:\\Delete Files\\TestLogFile.txt");

Данный вариант работает при любых настройках CodeGuard.
Но стоит раскоментировать первую строчку (не трогая вторую), и при включенном CodeGuard 
получаем "нечетный" Buffer и нецензурщину от NtCreateFile.
Причем не важно используем ли мы RTL_CONSTANT_STRING или расписываем его на месте вручную.
Эффект тот же. Т.е. данный способ декларации так влияет на инициализацию TestFile,
что не спасает даже последующая попытка использовать RtlInitUnicodeString.

P.S. Понимаю, что меня сейчас растерзают на месте, но скажу: Delphi себе таких шуток не позволяет smile

PM MAIL   Вверх
bsa
Дата 16.7.2008, 21:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Riply, повторяю, нечетный указатель это не криминал.
Если хочешь проверить, сделай:
Код
char *buffer = new char[100];
char *p = buffer + 1;
Или buffer будет нечетным или p. И от этого ты никуда не денешься.
PM   Вверх
Riply
Дата 17.7.2008, 02:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Цитата(bsa @  16.7.2008,  21:29 Найти цитируемый пост)
Riply, повторяю, нечетный указатель это не криминал.

Sorry, это я плохо излагаю свои мысли.
Я имела ввиду, что такая инициализация нашего Buffer`а, это криминал, как минимум, 
для нашего конкретного случая (аккуратно выражаясь), 
а скорее всего, это криминал для любой Nt-функции, принимающей на входе UNICODE_STRING.

Цитата(bsa @  16.7.2008,  21:29 Найти цитируемый пост)
Или buffer будет нечетным или p. И от этого ты никуда не денешься. 

Вот осторожность этой фразы меня и удивляет.
Ибо (при данном коде) я бы утверждала, что p будет нечетным, а buffer бутед выровнен на 32-битную границу,
а под BDS 2006 и выше на 64-битную. (Извращенные настройки среды мы не рассматриваем  smile )
PM MAIL   Вверх
bsa
Дата 17.7.2008, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Riply @ 17.7.2008,  02:34)
Вот осторожность этой фразы меня и удивляет.

я стараюсь быть осторожным  smile 
PM   Вверх
Riply
Дата 18.7.2008, 02:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Цитата(bsa @  17.7.2008,  21:10 Найти цитируемый пост)
я стараюсь быть осторожным  


Слава богу ! А то я уж испугалась, что данный код может возвращать "неровный" указатель smile

Ну вот. После того, как мы выяснили с какими неприятностями мы можем столкнутся,
встает несколько вопросов:
Как объявлять константы типа UNICODE_STRING, чтобы
 они сами были выровнены как минимум на 32-х битную границу
 и чтобы Buffer был выровнен как минимум на 32-х битную границу.
 Причем, чтобы это не зависило от внешних факторов (типа включения/выключения CodeGuard)
 и не влияло не остальной код ?

Второй вопрос:
есть у меня некая струтура. Код привожу на Delphi, ибо изясняясь только на этом языке (пока еще)
я могу быть уверена, что сказала именно то, что хотела сказать smile
Код

type
 PNamedGUID = ^TNamedGUID;
 TNamedGUID = packed record
  _Guid: TGUID;
  NameU: UNICODE_STRING;
 end;

const
_DiskDrive = 'DiskDrive'; // DiskDrive
 SysClassGuid_DiskDrive: TNamedGUID =
    (_Guid: '{4d36e967-e325-11ce-bfc1-08002be10318}';
     NameU: (Length: Length(_DiskDrive) shl SHR_WCHAR; 
            MaximumLength: Length(_DiskDrive) shl SHR_WCHAR + SizeOf(WideChar); Buffer: _DiskDrive));

Констант типа SysClassGuid_DiskDrive у меня как собак нерезанных smile
Как, соблюдая условия, описанные для UNICODE_STRING, инициализировать их ?
Причем сам _Guid должен быть выровнен как минимум на 64-х битную границу.
И можно ли инициализировать константу GUID строкой, как в Delphi
или мне вручную придется переводить строки типа '{4d36e967-e325-11ce-bfc1-08002be10318}'
в числовые значения ?

P.S. 
 Я не стала выносить вопрос по инициализаци чистого GUID в отдельную ветку, т.к.
 он неразрывно связан с выравниванием.


PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0633 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.