Total Commander Forum Index Total Commander
Форум поддержки пользователей Total Commander
Сайты: Все о Total Commander | Totalcmd.net | Ghisler.com | RU.TCKB
 
 RulesRules   SearchSearch   FAQFAQ   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Проблема компиляции - оптимизации программы VC++6.0

 
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander printer-friendly view
View previous topic :: View next topic  
Author Message
Parcan



Joined: 15 Dec 2004
Posts: 398
Location: Russian

Post (Separately) Posted: Sat Feb 19, 2005 17:50    Post subject: Проблема компиляции - оптимизации программы VC++6.0 Reply with quote

пишу плагин на Visual C++ 6.0

1. дебаг версия работает отлично, если компилировать с любой оптимизацией, то некоторые участки кода работают некорректно.
Пример:
читаю из файла в структуру, в ней все ок, передаю по ссылке в функцию, некоторые поля оказываются нулевыми.
обращаюсь к файлу может возникнуть ошибка обращения.
КАК МОЖНО БОРОТСЯ С ОПТИМИЗАЦИЕЙ И ЕСТЬЛИ ИНФА ПО ЭТОМУ?

2. в итоге откомпилировал без оптимизации но с избавлением от дебаг инфы, все вроде работает, но на некоторых файлах вылетает ошибка о чтении по неверному адрусу памяти, причем если файл скопировать в другую папку или переименовать все нормально, в дебаг версии такого не возникает, в итоге пытался найти место где возникает ошибка, так она на одном и том же файле возникает в разных участках кода, короче так и не смог ничего понять. Получается что какаято оптимизация всеравно происходит? и вообще кто тут виноват я или мелкомянкие.




Ну и еще вопросы по организации кода
а) как можно прицепить свою таблицу акселераторов к листеру, чтоб ввести горячие клавиши?
б) создаю окна (tabcontrol, static, richedit) как потомки моего основного окна, так как только я им передаю фокус, то все сообщения уже не попадают в WndProc моего основного окна, что делать?
Back to top
View user's profile Send private message
CaptainFlint



Joined: 14 Dec 2004
Posts: 6151
Location: Москва

Post (Separately) Posted: Sat Feb 19, 2005 19:14    Post subject: Reply with quote

Parcan
1. При чтении из файла в структуру часто бывают глюки, когда не учитывается выравнивание элементов структуры по 4-байтным адресам. Ты уверен, что ошибка возникает именно на этапе передачи структуры в функцию, а не при чтении из файла?
Ещё бывают проблемы, когда некорректно используется динамическая память: в дебаге и в релизе у неё различная внутренняя реализация.

2. Возможно, забываешь закрыть файл или опять же - динамическая память.

Вообще, ошибки слишком уж общие, чтобы можно было сказать, в чём конкретно баги. Во всяком случае, винить мелкомягких надо не в первую, а в самую последнюю очередь. Я уже огромное число раз натыкался на всякого рода ошибки, ругался на глючный VC++, а потом оказывалось, что ошибка у меня в коде.
Back to top
View user's profile Send private message
Dest



Joined: 17 Dec 2004
Posts: 44
Location: Беларусь(Минск,Барановичи)

Post (Separately) Posted: Sat Feb 19, 2005 20:49    Post subject: Reply with quote

>а) как можно прицепить свою таблицу акселераторов к листеру, чтоб ввести горячие клавиши?
Посмотри RegiserHotKey в MSDN :)
Можно перехватывать мессаги лисеру, но для новичков это будет сложновато понять ...
Back to top
View user's profile Send private message
Parcan



Joined: 15 Dec 2004
Posts: 398
Location: Russian

Post (Separately) Posted: Sun Feb 20, 2005 13:08    Post subject: Reply with quote

CaptainFlint
не читается все нормально и с выравниванием все ок, потеря происходит именно при передаче, такое ощущение, что часть структуры оседает в регистрах, это проявляется только при оптимизации кода.

с файлом тоже все нормально работаю, вообще участки кода в которых возникают ошибки после оптимизации я использую уже около 3 лет и я уверен что тут что-то с оптимизацией, поскольку у меня 18 классов унаследованы от одного и все используют одни и теже функции и после оптимизации ошибка может появится, а может и не появится

Пример:
вставляю в месте где собственно возникает ошибка sprintf() которая ничего нужного не делает и код после этого работат нормально, хоть убейте а в этом случае отличается только конечная реализация этого участка кода

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

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

Вобщем самая главная проблемма в том, что я впервые в жизни не могу понять в чем проблема, хотя бьюсь уже около 2 недель
Back to top
View user's profile Send private message
CaptainFlint



Joined: 14 Dec 2004
Posts: 6151
Location: Москва

Post (Separately) Posted: Sun Feb 20, 2005 14:00    Post subject: Reply with quote

Parcan
В DLL своя специфика. Нельзя сказать, что если EXE работает, то и DLL будет, это абсолютно неверно. Я лично на это наткнулся, когда писал плагин VirtualDisk. Запускаю программу filedisk.exe - всё отлично работает, диск подключается. Запускаю абсолютно тот же самый код, но скомпилированный в виде DLL - при подключении диск в системе появляется, но все обращения к нему обламываются. В конце концов выяснил: там не закрывались некоторые хендлы. Отдельной программе это пофигу: при завершении система сама всё закроет. А DLL, пока не закроется Тотал, не будет выгружаться, так и держит хендлы открытыми, блокируя доступ.

И это лишь один пример. Сколько их может быть неучтённых... Оно часто так бывает - вроде, всё очевидно, ошибиться негде. Ан нет...

И ещё: частенько ошибки вылезают не в том месте, где их причина. Вполне может оказаться, что ошибка чуть ли не в самом начале кода, но проявляется она только после определённых действий, причём в таком месте, где весь код начисто вылизан и абсолютно корректен. Поиск ошибок - очень непростое занятие...

А вообще, подобные обсуждения без собственно кода - это переливание из пустого в порожнее. Попробуй хоть как-то локализовать ошибку, урезать проект как можно сильнее, чтобы ошибка по-прежнему воспроизводилась, и выложи в общий доступ. Тогда, возможно, кто-то и найдёт, в чём проблема. Ну или в самом деле, докажет, что ошибка в компиляторе (такое тоже, конечно, не исключено, хотя и маловероятно). Кстати говоря, сервис-паки на студию установлены? А то мало ли...
Back to top
View user's profile Send private message
Ipse



Joined: 16 Dec 2004
Posts: 52

Post (Separately) Posted: Sun Feb 20, 2005 16:20    Post subject: Reply with quote

Parcan
Quote:
Пример:
вставляю в месте где собственно возникает ошибка sprintf() которая ничего нужного не делает и код после этого работат нормально, хоть убейте а в этом случае отличается только конечная реализация этого участка кода


У меня такое было несколько раз. Во всех случаях в ошибке были виноваты строковые операции. Где-то что-то недовыделил. Если там действительно строки (или вообще любые массивы), то проблему можно решить в лоб применением винапишных safe-функций (правда, совместимость с 9х может пострадать).
Back to top
View user's profile Send private message
Parcan



Joined: 15 Dec 2004
Posts: 398
Location: Russian

Post (Separately) Posted: Mon Feb 21, 2005 00:53    Post subject: Reply with quote

ПРИМЕР1: вот пример код нерабочий после оптимизации и код рабочий после оптимизации

//неработает
int TAce::
AnalyzeArcHead(ACE_BLOCK_HEAD& head)
{
WORD HEAD_SIZE = 0;
//...
HEAD_SIZE = TakeWord(head.HEAD_SIZE1, head.HEAD_SIZE2);
//...
m_loffset = HEAD_SIZE + 4;
//...
}

//гдето вызов
m_MSG = AnalyzeArcHead(m_BLOCK_HEAD);

посмтотрел через MessageBox() head.HEAD_SIZE1 и head.HEAD_SIZE2 равны 0, хотя m_BLOCK_HEAD.HEAD_SIZE1 и m_BLOCK_HEAD.HEAD_SIZE2 имеют значения, в итоге m_loffset = 0 + 4 = 4

//работает
int TAce::
AnalyzeArcHead(ACE_BLOCK_HEAD& head)
{
WORD HEAD_SIZE = 0;
//...
//начало ненужной вставки
char BufStr[MAX_LOADSTRING];
sprintf(BufStr, "%d\n%d", head.HEAD_SIZE1, head.HEAD_SIZE2);
//конец ненужной вставки
HEAD_SIZE = TakeWord(head.HEAD_SIZE1, head.HEAD_SIZE2);
//...
m_loffset = HEAD_SIZE + 4;
//...
}

//гдето вызов
m_MSG = AnalyzeArcHead(m_BLOCK_HEAD);

опять компилирую с оптимизацией, опа в head.HEAD_SIZE1 и head.HEAD_SIZE2 находятся нужные мне значения

мое мнение, что в первом случае нужные мне значения оказались только в регистрах процессора, а не в нужной мне структуре (после чтения из файла), во втором случае компилятор всетаки решил записать значения в мою структуру... КАКИЕ БУДУТ МЫСЛИ?


ПРИМЕР2
//при запуске плагина
HFONT hFontB = ::CreateFont(12, 0, 0, 0, FW_BOLD, FALSE, FALSE,
FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_ROMAN, "MS Sans Serif");

HFONT hFontN = ::CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_ROMAN, "MS Sans Serif");

HFONT hFontS = ::CreateFont(24, 0, 0, 0, FW_BOLD, FALSE, TRUE,
FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_ROMAN, "MS Sans Serif");

//при завершении работы
if (hFontB) { ::DeleteObject(hFontB); hFontB = 0; }
if (hFontN) { ::DeleteObject(hFontN); hFontN = 0; }
if (hFontS) { ::DeleteObject(hFontS); hFontS = 0; }

в MSDN написано либо будет создан шрифт, либо вернется NULL, соответственно я полагаю, что тут все должно отрабатывать корректно, вылавливал ошибку на участке удаления шрифтов...

все что я создаю в динамической памяти я инициализирую и даже на всякий случай удаляю в обратном порядке создания, проверил уже ну все, все что я делаю сам через new-delete проверил на 100%...

НЕДОУМЕНИЕ
и последнее есть у кого-нибудь предположение как возникновение ошибок может быть связано с путем файла и его именем, ведь как я уже говорил, что когда я находил такие ситуации я копировал или переименовывал файл и никаких ошибок на копии или переименованном оригинале не проявлялось, но на самом файле оригинале(непереименованном) возникают 100%. Все это проверялось только на Win98SE, на работе проверить все никак нет времени.

Ipse
ну незнаю сколько на си пишу а со строками всегда проблемы решаемы, поскольку покрайней мере на моей практике, ошибка со строками либо вылезает еще в дебаг версии, либо при первом запуске релиз версии.

Dest
RegisterHotKey, по тексту MSDN мне показалось, что хоткей будет срабатывать всегда независимо от текущего фокуса, хотя я в английском слаб могу и ошибатся, а как перехватывать сообщения хоть наметку дай, если будет время то меня не ломает поразбиратся, я вообще думал что на WinAPI писать легче, а когда попробовал (это впервый раз) аж офигел вспомнилось как на 1-2 курсах ассемблер изучали.
Back to top
View user's profile Send private message
Ipse



Joined: 16 Dec 2004
Posts: 52

Post (Separately) Posted: Mon Feb 21, 2005 14:39    Post subject: Reply with quote

Parcan

Quote:
мое мнение, что в первом случае нужные мне значения оказались только в регистрах процессора, а не в нужной мне структуре (после чтения из файла), во втором случае компилятор всетаки решил записать значения в мою структуру...


Это как? Передается адрес уже заполненной структуры:

Quote:
m_BLOCK_HEAD.HEAD_SIZE1 и m_BLOCK_HEAD.HEAD_SIZE2 имеют значения


и по дороге мистическим образом данные _переместились_ из памяти в регистры?

Если можно поподробнее кусок с заполнением структуры m_BLOCK_HEAD и полную процедуру парсинга AnalyzeArcHead()
Back to top
View user's profile Send private message
Parcan



Joined: 15 Dec 2004
Posts: 398
Location: Russian

Post (Separately) Posted: Mon Feb 21, 2005 20:05    Post subject: Reply with quote

Ipse
вставлять много давай на мыло кину

кстати я вдруг подумал в функции TakeWord() у меня используется ассемблерная вставка, может она както влияет, хотя во всех остальных местах при вызове функция сбоев не дает

//sobrat' WORD iz BYTEs
//lb - mladshiy BYTE
//hb - starshiy BYTE
WORD TArchive::
TakeWord(BYTE lb, BYTE hb)
{
WORD wrd = 0;
_asm
{
push eax
mov ah, hb //0xXX00
mov al, lb //0x00XX
mov wrd, ax //0xXXXX
pop eax
}
return wrd;
}

хотя как это при оптимизации может помешать ума не приложу.
Back to top
View user's profile Send private message
Ipse



Joined: 16 Dec 2004
Posts: 52

Post (Separately) Posted: Mon Feb 21, 2005 22:17    Post subject: Reply with quote

Мыло в приват кинул.

Врядли глючит асмовая вставка, но можно попробовать следующий изврат:

WORD* HEAD_SIZE = (WORD*) (&head.HEAD_SIZE1); // ИМХО, самый красивый вариант

естественно,

BYTE HEAD_SIZE1;
BYTE HEAD_SIZE2;

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

или так:

WORD HEAD_SIZE = head.HEAD_SIZE1;
HEAD_SIZE = ( HEAD_SIZE << 8 ) + head.HEAD_SIZE2;

про MAKEWORD() молчу, полагаю заменен сознательно (профайлер рулит ?)
Back to top
View user's profile Send private message
Parcan



Joined: 15 Dec 2004
Posts: 398
Location: Russian

Post (Separately) Posted: Tue Feb 22, 2005 19:36    Post subject: Reply with quote

Ipse
когда я себе представляю данные в регистрах я предпочитаю делать асмовские вставки, имхо нагляднее

выслал на мыло
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander All times are GMT + 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group