Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Странная ошибка в дебаг-версии


Автор: ksili 25.6.2009, 13:12
Здравствуйте.

Есть проект, который билдится и работает в релизе, но билдится и не работает в дебаге. У меня при запуске дебажной версии возникает ошибка с таким странным сообщением
Цитата

Порядковый номер 13161 не найден в библиотеке DLL mfc90ud.dll.

Ошибка происходит ещё на стадии загрузки всевозможных библиотек, т.е. когда ещё ни строчка своего кода не исполнилось. Строка в Output, во время которой происходит ошибка:
Цитата

'FWTray.exe': Loaded 'D:\WINDOWS\system32\msimg32.dll'

Всё это как-то не давало мне понять где же хотя бы примерно искать ошибку. Но появилась зацепка. Другой человек, который запускал дебажный билд на другом компе сказал, что у него ошибка другая:
Цитата

Run-Time Check Failure #0 - The value of ESP was not properly saved across a
function call.  This is usually a result of calling a function declared with
one calling convention with a function pointer declared with a different
calling convention.

Эта ошибка более описана в интернете, что я и изучил. При этом вдобавок известен код,где она происходит:
Код

        if (IsVista())
        {
            HMODULE lib = LoadLibrary(L"dwmapi.dll");
            if (lib)
            {
                HRESULT (*DwmIsCompositionEnabledProc)(BOOL *pfEnabled);
                (FARPROC&)DwmIsCompositionEnabledProc = GetProcAddress(lib, "DwmIsCompositionEnabled");
                if (DwmIsCompositionEnabledProc)
                {
                    BOOL fDwmEnabled;
                    if (FAILED(DwmIsCompositionEnabledProc(&fDwmEnabled)))
                        fDwmEnabled = FALSE;
                    if (fDwmEnabled)
                    {
                        g_DwmIsCompositionEnabled = true;
                        ButtonWindow::Create();
                        //trace(g_enableLocalLog, "ButtonWindow created\n");    
                    }
                }
                FreeLibrary(lib);
            }
        }

Этот код используется В Висте для определения наличия композитного режима в теме рабочего стола. Ошибка происходит на строке вызова импортированной функции if (FAILED(DwmIsCompositionEnabledProc(&fDwmEnabled))) 
Собственно, я делаю билд  в Win XP (русская) и у меня этот код вообще не исполняется, а вот тот человек, не знаю - в Висте или в XP и вдобавок английской.

Согласно тому, что я нашёл в инете про эту ошибку, я попробовал исправить строку объявления указателя на функцию на 
Код

HRESULT (__stdcall *DwmIsCompositionEnabledProc)(BOOL *pfEnabled);

Код

HRESULT (__cdecl *DwmIsCompositionEnabledProc)(BOOL *pfEnabled);

и
Код

HRESULT (__fastcall *DwmIsCompositionEnabledProc)(BOOL *pfEnabled);

Однако у меня всё также Порядковый номер 13161 не найден в библиотеке DLL mfc90ud.dll.

Есть у кого-нибудь хоть какие-нибудь ещё мысли, что в этом коде можно поправить?

Автор: xvr 25.6.2009, 13:22
Мысль пока единственная - эти ошибки НИКАК друг с другом не связанны

По поводу 
Цитата

Порядковый номер 13161 не найден в библиотеке DLL mfc90ud.dll.
 - у вас случайно не завалялось несколько разных mfc90ud.dll? Похоже, что библиотека импорта (с которой было слинкованно приложение) от другой версии  mfc90ud.dll

Автор: ksili 25.6.2009, 13:30
Цитата(xvr @  25.6.2009,  17:22 Найти цитируемый пост)
у вас случайно не завалялось несколько разных mfc90ud.dll? Похоже, что библиотека импорта (с которой было слинкованно приложение) от другой версии  mfc90ud.dll

У меня ввобще два раздела. В одном стоит Win XP SP3 с MSVS 2005, а на втором та же Win XP SP3, но с MSVS 2008. Этот проект выполняется в MSVS 2008. Как мне быть уверенным, что при сборке случайно не используется mfc90ud.dll из MSVS 2005? В свойствах проекта посмотрел - везде, где стоит имя диска, оно указано верно.

Добавлено через 4 минуты и 17 секунд
поправочка: в MSVS 2005 mfc90ud.dll вообще нет. Там mfc80ud.dll.
Зато в MSVS 2008 их несколько в разных папках

Автор: xvr 25.6.2009, 13:55
Цитата(ksili @ 25.6.2009,  13:30)
Цитата(xvr @  25.6.2009,  17:22 Найти цитируемый пост)
у вас случайно не завалялось несколько разных mfc90ud.dll? Похоже, что библиотека импорта (с которой было слинкованно приложение) от другой версии  mfc90ud.dll

Как мне быть уверенным, что при сборке случайно не используется mfc90ud.dll из MSVS 2005? В свойствах проекта посмотрел - везде, где стоит имя диска, оно указано верно.


dll ищется run-time по стандартным путям. Директории, которые прописанны в VS на это никак не влияют

Цитата

Зато в MSVS 2008 их несколько в разных папках
Они все одинаковые, или разные? Попробуйте найти нужную, и положить ее рядом с exe'ником программы

Еще можно отключить в VS сборку с динамическими библиотеками (использовать статический run-time)

Автор: Earnest 25.6.2009, 16:15
Этот порядковый номер используется вместо имени функции на импорте. Он должен быть прописан в def-файле библиотеки. Похоже, линкуется не та версия, которая потом используется. Можно просто поиском посмотреть это число.

Автор: ksili 26.6.2009, 05:49
Цитата(xvr @  25.6.2009,  17:55 Найти цитируемый пост)
Они все одинаковые, или разные?

Их 9 штук и они все разные

Цитата(xvr @  25.6.2009,  17:55 Найти цитируемый пост)
Попробуйте найти нужную, и положить ее рядом с exe'ником программы

Попробовал положить рядом с exe'шником две наиболее вероятные из них: лежащие по путям D:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugMFC\mfc90ud.dll и D:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dll\x86\MFC90UD.DLL. Ошибка осталась.
Остальные лежат в папках 
D:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dll\mipsiv_fp\, 
D:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dll\mipsiv\, 
D:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dll\mipsii_fp\, 
D:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dll\mipsii\, 
D:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dll\armv4i\, 
D:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dll\armv4\, и 
D:\Program Files\Microsoft Visual Studio 9.0\VC\ce\dll\sh4\
Так что думаю они вообще из другой оперы

Цитата(Earnest @  25.6.2009,  20:15 Найти цитируемый пост)
Этот порядковый номер используется вместо имени функции на импорте. Он должен быть прописан в def-файле библиотеки. Похоже, линкуется не та версия, которая потом используется. Можно просто поиском посмотреть это число.

Из двух проверенных dll только  в одной (самой большой, которая в папке redist) был найден ординал 13161 в таблице экспорта.  Но помещение её в папку с экзешником ошибку при рантайме не исправило.

Цитата(xvr @  25.6.2009,  17:55 Найти цитируемый пост)
Еще можно отключить в VS сборку с динамическими библиотеками (использовать статический run-time)

Как это сделать? Я чё-то в свойствах проекта такой настройки не нашёл. 
Ещё момент: в проекте у меня экзкшник и dll, которая внедряется в другие процессы. Не увеличится ли значительно её размер при использованиии  статического run-time? Это нежелательно.

Автор: jonie 26.6.2009, 07:26
Цитата

Из двух проверенных dll только  в одной (самой большой, которая в папке redist) был найден ординал 13161 в таблице экспорта.  Но помещение её в папку с экзешником ошибку при рантайме не исправило.
возьмите depends.exe и натравите на свой exe шник. Посмотрите чего там выдаст.

Автор: ksili 26.6.2009, 07:53
Цитата(jonie @  26.6.2009,  11:26 Найти цитируемый пост)
возьмите depends.exe и натравите на свой exe шник

А выдал он следующее:
во-первых, не нашёл DWMAPI.DLL, но это понятно, т.к. это вистовская библиотека, а я в XP.
во-вторых, подсвечена MFC90UD.DLL. Щёлкнул по ней, открылось второе окно, в котором показывается, что у этой длл зависимость от MSVCR90D.DLL и она не найдена.

Что ещё интересно, MFC90UD.DLL берется из папки D:\windows\winsxs\x86_microsoft.vc90.debugmfc_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_2a62a75b. чё-то я не догадывался, что они ещё могут быть в папках винды. Там оказывается таких папок куча, причём рядом с этой папкой лежит папка x86_Microsoft.VC90.DebugCRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_597c3456, а в ней эта самая MFC90UD.DLL. Почему она не находится - для меня загадка.

Автор: ksili 26.6.2009, 08:10
Кстати в dll из D:\windows\winsxs\x86_microsoft.vc90.debugmfc_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_2a62a75b в экспорте не нашлось 13161.
поэтому я заменил её на ту, в которой она есть и программа запустилась в дебаге! Но все же мне кажется это неполным решением, т.к. я не понимаю из-за чего так произошло и не поломал ли я чего-нибудь другого такой заменой.

Автор: jonie 26.6.2009, 09:04
Цитата

Почему она не находится - для меня загадка. 
насколько я понимаю это связано с манифестом (?) посмотрите какой в манифесте указан (программой вроде reshacker можно посмотреть, или любой другой умеющей работать с ресурсами)

Автор: ksili 26.6.2009, 09:40
У меня манифест открывается практически как XML-файл. Из существенного там:
Код

- <dependency>
- <dependentAssembly>
  <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b" /> 
  </dependentAssembly>
  </dependency>

Т.е. используется версия библиотеки 9.0.21022.8. Это как раз та, в которой нет 13161. А я фактически заменил её на библиотеку версии 9.0.30729.1. 
Если я просто перепишу в манифесте версию, будет ли это корректно? Дело в том, что по пути D:\windows\winsxs\ нет папки DebugCRT с такой версией, там только с версией 9.0.21022.8. 

Автор: jonie 26.6.2009, 18:58
ты можешь и свой манифест написать при желании.
Например для common controls:
1) делаем xml файл с именем "программа.exe.manifest"
Код

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 

<assemblyIdentity 

version="1.0.0.0" 

processorArchitecture="X86" 

name="CompanyName.ProductName.YourApp" 

type="win32" 

/> 

<description>Your application description here.</description> 

<dependency> 

<dependentAssembly> 

<assemblyIdentity 

type="win32" 

name="Microsoft.Windows.Common-Controls" 

version="6.0.0.0" 

processorArchitecture="X86" 

publicKeyToken="6595b64144ccf1df" 

language="*" 

/> 

</dependentAssembly> 

</dependency> 

</assembly>

2) открываем rc файл как код и вписываем строку:
Код

CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "Программа.exe.manifest"

3)добавляем в проект файл "Программа.exe.manifest"....
усе...
а ну, может тебе в секции linker настройки отключить генерирование манифеста можно в случае его ручного "заведения"....

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)