Присвоение пользовательскому интерфейсу, написанному на C / CLI, значения null может привести к аварийному завершению работы программы

#c# #interface #c -cli #kernel32

#c# #интерфейс #c -cli #kernel32

Вопрос:

У меня есть пользовательский.Сетевой интерфейс, написанный на C / CLI:

 public interface class IBackgroundExtractor
{
};
  

В моем приложении на C # интерфейс используется:

 private IBackgroundExtractor extractor = null;
  

Приведенный выше код работает без сбоев на моем компьютере (на котором установлена Visual studio), но на другом компьютере произошел сбой (без установки Visual Studio):

 AppName: speedtest.exe   AppVer: 1.0.0.0     ModName: kernel32.dll
ModVer: 5.1.2600.5512    Offset: 00012aeb
  

Если я удалю присвоение null, код будет выполняться на обоих компьютерах:

 private IBackgroundExtractor extractor;
  

Однако я создал другой интерфейс на чистом C #. Присвоение интерфейсу значения null не приведет к аварийному завершению работы программы:

 interface IAnotherInterface
{
}
private IAnotherInterface test = null;
  

Что не так в моем интерфейсе C / CLI?

[Примечания]

Я создал два «чистых» новых проекта для тестирования, первый из которых представляет собой библиотеку классов C / CLI (Новый проект -> Visual C -> CLR -> Библиотека классов). Добавьте следующие строки в файл .h библиотеки:

 public interface class ITest {
};
  

Затем создайте проект приложения Windows Form (Net Project -> Visual C # -> Windows -> Windows Forms Application) и объявите переменную ITest в функции main:

 static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());

    ITest xxx = null;
}
  

Программа будет запущена на компьютере разработчика (установлена Visual studio), но произойдет сбой на двух других компьютерах. Один из вышедших из строя компьютеров является физической машиной, а другой — виртуальной машиной.

Я использую Windows XP Pro SP3, Visual Studio 2010 и .Net Framework 4.0.

Комментарии:

1. Это невозможно, среда CLR всегда инициализирует ссылки значением null, независимо от того, делаете вы это явно или нет. Напишите лучший обработчик необработанных исключений, реализуйте AppDomain. CurrentDomain. Событие необработанного исключения и регистрирует или отображает значение e.ExceptionObject. toString().

2. Что именно происходит, когда он «вылетает»? Есть ли сообщение об ошибке? Что это за сообщение?

3. Главное окно программы не отображается. Появляется диалоговое окно с текстом ошибки: ‘test.exe вызвало ошибку и и должно быть закрыто. Приносим извинения за доставленные неудобства.’ после двойного щелчка по программе.

4. В ошибке сообщается об ошибке kernel32.dll : AppName: wpfapplication1.exe Версия приложения: 1.0.0.0 ModName: kernel32.dll Модер: 5.1.2600.5512 Смещение: 00012aeb

Ответ №1:

Вы убедились, что на целевых компьютерах установлена правильная версия среды выполнения Microsoft Visual C ? (В вашей среде разработки это уже будет установлено, но ни одна текущая версия Windows не включает эту среду выполнения по умолчанию).

Если вы настроили свой проект C / CLI на использование «БЕЗОПАСНОГО» режима, он вообще не будет ссылаться на среду выполнения Microsoft Visual c (только на .NET). Смотрите это для справки: Чистый и проверяемый код. Если вам нужно создавать собственные материалы, то очень высока вероятность того, что вам потребуется установить последнюю версию Visual C runtime. Распространяемый пакет вы можете приобрести здесь: Распространяемый пакет Microsoft Visual C 2010.

Если вы хотите убедиться, что проблема именно в этом, вы можете использовать sxstrace инструмент для диагностики этих проблем (полезное руководство).

Ответ №2:

Присвоение null, вероятно, является не ошибкой, а триггером для ошибки. Это присвоение значения null, вероятно, является первой строкой кода, которая обращается к сборке C / CLI. Таким образом, еще до того, как будет выполнено присвоение этого null, инициализируется неуправляемая часть сборки C / CLI. Вероятно, именно здесь возникает ошибка.