информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Все любят медПортрет посетителяСетевые кракеры и правда о деле Левина
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[C++] Это очень страшно. 28.09.03 01:41  Число просмотров: 1233
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
Cпасибо, Tlo, за мнение.

> Ничего нового, конечно, но может поможет.

Поможет ;)
Тем более, что это мнение человека, который, как видно, в этом направлении уже "копал".
<programming>
[c++] afx_manage_state – всегда ли? 25.09.03 06:39  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
Возможно, из-за недостатка моего опыта вопрос покажется очень простым,
но прошу не отсылать к MSDN. Там я не нашёл однозначного ответа «на все случаи жизни».

Вопрос в том, собственно, а всегда ли необходимо использовать этот макро в Regular DLL MFC?

1) DLL изготавливается не с «uses the shared MFC libraries», a «statically linked MFC».
Есть подозрение, что в этом случае AFX_MANAGE_STATE не нужен вовсе. Так ли?

2) Практически во всех статьях MSDN сказано, что если «shared MFC libraries», то используйте AFX_MANAGE_STATE во всех экспортируемых функциях (я бы поправил здесь писателей от мелкософт – не экспортируемых, а вызываемых).

Но так ли?

Положим, есть класс в «Regular DLL MFC whis shared MFC libraries»:

class CI_ODBCquery: public IQueryInterface { private: CRecordset* Query; … … CString connection; CString error; LPCTSTR error2; bool msgerror; public: void __stdcall Connection (LPCTSTR ConnectionStr); void __stdcall CanErrorMessage(const int can_msg); void __stdcall ErrorMessage (LPTSTR* outval ); void __stdcall ErrorMessage2 (LPTSTR* outval ); … … };

Четыре функции в конце декларации класса CI_ODBCquery доступны программисту для вызовов после «загрузки» DLL, т.е. программист вызывает эти функции DLL непосредственно.

Функция CanErrorMessage(const int can_msg) совсем простая. Она устанавливает msgerror в true/false:

void __stdcall CI_ODBCquery::CanErrorMessage(const int can_msg) { msgerror = can_msg ? true:false; }

Спрашивается, ну зачем здесь что-то «синхронизировать» в MFC при помощи макро AFX_MANAGE_STATE? Думаю, не требуется макро AFX_MANAGE_STATE. Так?

Функция ErrorMessage2(LPTSTR* outval ) – не сложнее. Она только «возвращает» указатель на нуль-терминированную строку error2:

void __stdcall CI_ODBCquery::ErrorMessage2(LPTSTR* outval) { *outval = error2; }

Не требуется макро AFX_MANAGE_STATE. Так?

Функция ErrorMessage(LPTSTR* outval ) – чуть «сложнее». Она «возвращает» указатель на нуль-терминированную строку – буфер класса MFC CString error:

void __stdcall CI_ODBCquery::ErrorMessage1(LPTSTR* outval) { *outval = (LPTSTR)((LPCTSTR)error); }

Здесь, как бы и самое место тому AFX_MANAGE_STATE, поскольку речь идёт об непосредственном обращении к объекту error класса MFC CString. Но!!! Переменная error была инициализирована, а потом возможно «перезаписана» неоднократно совершенно из других приват-функций класса CI_ODBCquery. Сомнительно, что и здесь следует использовать AFX_MANAGE_STATE. Так?

С функцией Connection (LPCTSTR ConnectionStr), см. выше, возможно дело чуть сложнее, поскольку из её тела происходит «перераспределение» памяти, используемой, переменной CString connection:

void __stdcall CI_ODBCquery::Connection(LPCTSTR ConnectionStr) { connection = _TEXT("DSN="); connection += ConnectionStr; connection += _TEXT(";UID=;PWD="); … … }

Казалось бы, что раз мы «напрямую» задействуем MFC CString «из вне», то наличие AFX_MANAGE_STATE просто обязательно. Но!!! Переменная connection была инициализирована пустой строкой в конструкторе CI_ODBCquery до того, как программист может сделать вызов Connection(….). Я могу сильно ошибаться, но, на мой взгляд, класс CString слишком «прост» для того, что бы необходима была «синхронизация неизвестно чего при помощи макро AFX_MANAGE_STATE.

3) Возможно, то, что ниже - просто моё брюзжание. Но, например, ЭТО (и подобное ему) просто раздражает:

Knowledge Base Articles BUG: Wincore.cpp Line 879 Assert When Using MFC Classes
Q192853
….


STDMETHODIMP CTest::TestMethod() { AFX_MANAGE_STATE(afxGetStaticModuleState()) CDatabase db; db.OpenEx("DSN=LocalServer;Database=pubs;UID=sa;PWD=;"); db.Close(); return S_OK; }

the assertion dialog appears.


Или ещё смешнее:


Visual C++ Concepts: Adding Functionality
Exported DLL Function Entry Points
….
….
AFX_MANAGE_STATE does not need to be put into every function in the DLL. For example, InitInstance can be called by the MFC code in the application without AFX_MANAGE_STATE because MFC automatically shifts the module state before InitInstance and then switches it back after InitInstance returns. The same is true for all message-map handlers. Regular DLLs actually have a special master window procedure that automatically switches the module state before routing any message.

Т.е., товарищи от мелкософт здесь и выше говорят, о том, что вообщем-то AFX_MANAGE_STATE не только не всегда следует использовать, но «просто так» - это ещё и вредно.

PS. Прошу подсказать мне, что же на самом деле происходит?
[C++] Это очень страшно. 27.09.03 18:09  
Автор: Tlo Статус: Незарегистрированный пользователь
<"чистая" ссылка>
(Ох, как вспомню как я бился с dll'ками, статически линкуемыми с MFC, страшно становиться).

Теперь немного по делу. Если ты принимаешь правила framework'а. то принимаешь их полностью. Поэтому, если тебе говорят, что переключать контексты надо во всех экспортируемых, то надо их переключать. А иначе придется делать заключения ореализацииклассов famework'а (так как ты, безусловно корректно, сделал для CString), что не всегда возможно, особенно, если хост и dll'ка собраны с разными версиями билдами MFC (не говоря уже о разных версиях).

Но это все баблинг (и наверное, void, все-таки не для тебя, а для менее искушенных). А что касается непосредственно AFX_MODULE_STATE, то если не ошибаюсь он хранит только инфу, необходимую для mfc'овых хуков - любые функции dll, создающие окна, например те, которые работают с mfc'овыми CAsyncSocket'ами (отгадайте почему :), должны переключить контекст -, и что-то там с DAO.

Здравый же смысл, действительно подсказывает, что тривиальные функции, неимеющие сношений с MFC не должны переключать контекст модулей (операция, прямо скажем сама по себе нетривиальная). Но опять-таки подчеркну свое imho (входящее в резонанс с mfc'овым ho) - если framework навязывает - надо выполнять. Это как с параметрами операций типа IUnknown - можно AddRef не делать - и так работать будет, но это уже отклонение от стандарта, и вся ответственность лежит уже на вас.

Ничего нового, конечно, но может поможет.
[C++] Это очень страшно. 28.09.03 01:41  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
Cпасибо, Tlo, за мнение.

> Ничего нового, конечно, но может поможет.

Поможет ;)
Тем более, что это мнение человека, который, как видно, в этом направлении уже "копал".
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach