Поделиться через


Практическое руководство. Диагностика и устранение проблем совместимости сборок (C++/CLI)

В этом разделе рассматривается, что может произойти, если версия сборки, которая использовалась при компиляции, не совпадает с версией сборки, используемой при выполнении, и как избежать этой проблемы.

Когда сборка компилируется, она может ссылаться на другие сборки с помощью директивы #using.Во время компиляции компилятор обращается к этим сборкам.Сведения из этих сборок используются для принятия решений по оптимизации.

Тем не менее, если сборка, на которую существует ссылка, будет изменена и перекомпилирована, а основная сборка при этом не будет перекомпилирована, то сборки могут стать несовместимыми.Решения по оптимизации, которые сначала были верными, могут стать некорректными по отношению к новой версии сборки.Следствием возникшей несовместимости могут стать различные ошибки во время выполнения.Не существует специального исключения, которое могло бы возникать в таких случаях.Каким именно образом проявится ошибка во время выполнения, зависит от того изменения кода, которое привело к проблеме.

Этих ошибок не должно быть, если все приложение строится заново, например, при выпуске окончательной версии продукта.Для всех выпускаемых открытых сборок необходимо указать официальный номер версии, что позволит избежать проблем несовместимости.Дополнительные сведения см. в разделе Управление версиями сборок.

Диагностика и устранение ошибок несовместимости

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

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

  3. Проверьте отметки времени всех сборок, на которые ссылается ваше приложение.

  4. Если отметка времени какой-либо из этих сборок является более поздней, чем отметка времени последней компиляции приложения, то приложение устарело.В этом случае перекомпилируйте приложение с самыми последними версиями сборок и внесите в его код необходимые изменения.

  5. Вновь запустите приложение, выполните шаги, необходимые для воспроизведения проблемы, и убедитесь, что исключение не возникает.

Пример

Приведенная ниже программа иллюстрирует эту проблему путем снижения уровня доступности метода и выполнения обращения к этому методу из другой сборки без ее перекомпиляции.Сначала скомпилируйте changeaccess.cpp.Это связанная сборка, которая будет изменена.Затем скомпилируйте referencing.cpp.Компиляция выполнится успешно.Теперь понизьте уровень доступности вызываемого метода.Перекомпилируйте changeaccess.cpp с флагом /DCHANGE_ACCESS.Метод станет защищенным. Поскольку он не закрыт, его все еще можно вызывать.Снова запустите приложение referencing.exe, не перекомпилируя его.В результате произойдет исключение MethodAccessException.

// changeaccess.cpp
// compile with: /clr:safe /LD
// After the initial compilation, add /DCHANGE_ACCESS and rerun
// referencing.exe to introduce an error at runtime. To correct
// the problem, recompile referencing.exe

public ref class Test {
#if defined(CHANGE_ACCESS)
protected:
#else
public:
#endif

  int access_me() {
    return 0;
  }

};

// referencing.cpp
// compile with: /clr:safe 
#using <changeaccess.dll>

// Force the function to be inline, to override the compiler's own
// algorithm.
__forceinline
int CallMethod(Test^ t) {
  // The call is allowed only if access_me is declared public
  return t->access_me();
}

int main() {
  Test^ t = gcnew Test();
  try
  {
    CallMethod(t);
    System::Console::WriteLine("No exception.");
  }
  catch (System::Exception ^ e)
  {
    System::Console::WriteLine("Exception!");
  }
  return 0;
}

См. также

Ссылки

Директивы #using (C++)

Другие ресурсы

Управляемые типы (C++/CLI)