Все тесты не пройдены, невозможно получить тип и FileNotFoundException, если определенная строка кода в одном тесте после добавления теста fmod Visual C++

Я понял, что вызвало проблему, но я до сих пор не знаю почему - это произошло, когда я начал использовать fmod, и это должно быть как-то связано с тем, как компоновщик решает ввести и выполнить статические библиотеки и .dll. Мой тестируемый код является статической библиотекой; это относится к fmodex_vc, еще одной статической библиотеке, которая в какой-то момент (хотя я не знаю, когда) решает загрузить свою fmodex.dll. (Который находится в той же директории, что и все остальное, поэтому я не знаю, почему он его не найдет.) Насколько я знаю, тестируемый код абсолютно не вызывает функции инициализации fmod, но, возможно, fmod имеет некоторые статические глобальные инициализаторы, которые инициализируют себя и загружают в dll? И этот код извлекается только в том случае, если код в модуле, который его использует, используется?

Я тестирую неуправляемый код C++ с помощью тестовой среды Visual Studio, и когда я начал использовать fmod, он перестал работать: каждый тест, даже «тестовые» тесты, которые ничего не делают, будет сообщать (обернутый для удобства чтения):

Unable to get type SlidersTest.UnitTest1, SlidersTest.
    Error: System.IO.FileNotFoundException: 
    The specified module could not be found.
    (Exception from HRESULT: 0x8007007E)

После множества проб и ошибок, исключая файлы .cpp и добавляя их повторно, я обнаружил, что только один из тестовых файлов вызывает проблему; и это происходит только в том случае, если эта строка вызывается:

EntityMgr::Init();

Интересно, что все тесты начинают давать сбой с этим сообщением, если эта строка есть в коде. EntityMgr::Init() — это функция, которая делает очень мало:

EntityMgr* EntityMgr::instG = null;

а также

void EntityMgr::Init()
{
   instG = new EntityMgr;
}

а также

class EntityMgr
{
private:
   static EntityMgr* instG;
public:
   EntityMgr()   // does nothing beyond the default 
   {
   }

   static void Init();
   static EntityMgr* Inst() { return instG; }

   ...

   vector<Entity> entitiesG;
};

Entity, FWIW, — довольно ванильный класс без указателей, просто различные float для его полей.

  • Независимо от того, как я запускаю тесты (из режима тестирования, запускаю выбранные, запускаю все, запускаю из командной строки, из меню тестирования), я получаю сообщение об ошибке.
  • Попытка войти в тест с помощью отладчика не удалась — тест завершился неудачно до того, как отладчик вмешается. Настройка отладчика на прерывание системных исключений также ничего не дала.
  • Тестируемый код представляет собой статический .lib. Поддержка CLR — /clr.
  • О, и это только в: если я вызываю статическую функцию-член Entity, то же самое. Если я перенесу указанную статическую функцию за пределы класса, то же самое. Но если я перенесу эту функцию в другой модуль, все в порядке.

Если я настрою отладчик на прерывание любого исключения, я получу кое-что интересное:

First-chance exception at 0x7c812aeb in vstesthost.exe: Microsoft C++ exception: HRException at memory location 0x05129890..

Там, конечно, нет исходного кода. Вот стек вызовов:

     kernel32.dll!7c812aeb()    
    [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]  
    kernel32.dll!7c812aeb()     
    [External Code] 
    msvcr80.dll!78158ed7()  
    msvcr80.dll!78158e34()  
    msvcr80.dll!78158047()  
    msvcr80.dll!7815850e()  
    msvcr80.dll!78158872()  
    msvcr80.dll!78158a57()  
    msvcr80.dll!78158b11()  
    ntdll.dll!7c9032a8()    
    ntdll.dll!7c90327a()    
    ntdll.dll!7c92a9ef()    
    ntdll.dll!7c90e46a()    
    kernel32.dll!7c812aeb()     
    kernel32.dll!7c812aeb()     
    kernel32.dll!7c812aeb()     
    msvcr80.dll!78139c4d()  
    msvcr80.dll!781323ff()  
    msctf.dll!74755764()    
    msctf.dll!74721557()    
    ws2_32.dll!71ab12bb()   
    ntdll.dll!7c90118a()    
    ntdll.dll!7c91b084()    
    ntdll.dll!7c90de7c()    
    ntdll.dll!7c90d04c()    
    ntdll.dll!7c90e43f()    
    kernel32.dll!7c80b713()     

А вот трассировка стека, которую сообщает mstest — я не получаю из нее ничего полезного.

Unable to get type SlidersTest.game_EntityMgr_test, SlidersTest. Error: System.IO.FileNotFoundException: The specified module could not be found. (Exception from HRESULT: 0x8007007E)
   at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
   at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.LoadFrom(String assemblyFile)
   at Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestExecuter.GetType(UnitTestElement unitTest, String type)
   at Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestExecuter.ResolveMethods().

Почему fmod делает это?


person Jamie Fristrom    schedule 09.04.2009    source источник
comment
Я не думаю, что у вас есть код, который позволил бы нам воссоздать проблему? А что будет, если создать обычное консольное приложение (а не MSTest), содержащее такой же код?   -  person jalf    schedule 23.04.2009
comment
Может помочь, а может и не помочь в этом контексте, но каждый раз, когда я вижу опубликованную трассировку стека, заполненную библиотеками MS DLL, я не могу не указать на преимущество настройки Visual Studio для использования сервера символов MS. Только один из первых результатов Google для базовой настройки: geekswithblogs.net/mskoolaid. /archive/2005/12/17/63418.aspx Тогда, по крайней мере, вы увидите множество имен функций в этой трассировке стека, которые МОГУТ помочь вам диагностировать проблему.   -  person imaginaryboy    schedule 28.04.2009


Ответы (7)


Я предлагаю запустить ваше приложение в режиме профиля Dependency Walker (http://www.dependencywalker.com/). Он может записывать все попытки загрузки DLL и EXE-файлов вместе с результирующими кодами ошибок — похоже, что ошибка «Файл не найден» возникает из-за косвенной зависимости — возможно, из-за связывания FMod.

В этом случае профилирование вашего приложения с помощью Dependency Walker покажет одну или несколько неудачных попыток загрузить библиотеку. Один из них будет виновником ошибки.

person Katelyn Gadd    schedule 14.05.2009

Может быть, для этого файла было изменено какое-то свойство? Вероятно, уже смотрели на это, но убедитесь, что все настройки взяты из «Наследовать от родителя» в Visual Studio.

Джей

person Community    schedule 09.04.2009
comment
Два файла, тот, в котором функция работает, и тот, в котором она не работает, похоже, имеют одинаковые свойства: я дважды проверил, открыв свойства в двух экземплярах VS. - person Jamie Fristrom; 11.04.2009

Мое лучшее предположение из того, что вы опубликовали до сих пор, заключается в том, что исключение генерируется где-то внутри загрузчика типов CLR - похоже, что сборка, от которой вы косвенно зависите, либо не находится в GAC, либо не t копируется в тестовый каталог.

Есть ли фактическая трассировка стека в результатах теста? Это может помочь сузить тип (ы), который он пытается загрузить.

person Alex Lyman    schedule 09.04.2009

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

person Joel Martinez    schedule 10.04.2009
comment
Или вернитесь в исходный контроль. К сожалению, у нас были проблемы с нашим хостом, и у меня есть около недели изменений в одной регистрации, поэтому я не знаю точное изменение, которое сломало его. - person Jamie Fristrom; 11.04.2009

Можно ли настроить Visual Studio на прерывание всех исключений, независимо от того, откуда они исходят во время отладки?

Звучит так, как будто космические лучи или неисправный жесткий диск вызвали повреждение тестовой .dll, или dll, которую вы создаете, повреждена (постоянно). Перед повторной установкой всей Visual Studio вы можете попросить ее выполнить ремонт, который должен проверить наличие несоответствий между вашей текущей установкой и тем, что находится на вашем установочном носителе.

person Jeff    schedule 10.04.2009

Как FMod .dll попадает в ваш тестовый каталог? Вы настроили его для копирования туда, где mstest хочет, чтобы тест выполнялся? Обратите внимание, что «Копировать в выходной каталог» на самом деле этого не делает. Есть еще какой-то метод, но я не могу точно вспомнить, что это такое.

person Jeff    schedule 14.04.2009

Я бы запустил его в отладчике и проверил вывод запуска, в частности, строку «loading path\fmodex.dll», чтобы убедиться, что он загружает правильную dll.

Я видел подобные ошибки при смешивании dll из разных конфигураций.

person Community    schedule 20.05.2009