После развертывания нашей огромной распределенной системы на одном из наших клиентов возникает непредвиденная ошибка. В ходе исследования мы заменяем сборку, вызвавшую ошибку, на ту, в которую добавили какой-то диагностический код. Используемая нами dll построена в режиме отладки. И вдруг все работает!
Замена отладочной dll на версию выпуска (с диагностическим кодом) снова вызывает сбой.
В нашем коде нет директив прекомпилятора, условных атрибутов отладки и т. д. Проблема была обнаружена в двух разных местах установки, в то время как она отлично работает еще на нескольких.
(В проекте используется смесь C# и VB.NET, проблемная сборка - VB.NET .., если это имеет значение)
Итак, вопрос: Что вы делаете в подобных ситуациях? А в чем может быть причина - вообще? Любые советы по отладке этой проблемы приветствуются.
Я еще не смог это исправить, но это исключение с нулевой ссылкой (так что это действительно не помогает, верно !?).
Может, вместе со стеком вызовов. Изучение стека вызовов - одно из первых действий, которое вы должны сделать.





По причинам ... ну, поможет намек на симптом. Одна из возможностей заключается в том, что у вас есть код для такого метода, как Debug.WriteLine, который имеет побочные эффекты (т.е. заставляет его работать). Вызовы методов, помеченных как [Conditional(...)], не компилируются, если у вас не определены правильные символы, поэтому все, что помечено как [Conditional("DEBUG")], будет автоматически удалено.
Это также может быть ошибка компилятора, но это маловероятно (но не невозможно).
Какой симптом? Как это ломается?
В качестве примера вышеизложенного:
static string Bar { get; set; }
static void Main()
{
Bar = "I'm broken";
Debug.WriteLine(Foo());
Console.WriteLine(Bar);
}
// note Foo only called in DEBUG builds
static string Foo()
{
Bar = "I'm working";
return "mwahahah";
}
При компиляции в режиме DEBUG выводится «Я работаю»; при компиляции в режиме RELEASE выводится сообщение «Я сломался». Похоже это звучит? Убедитесь, что вы не вызываете какие-либо методы отладки напрямую с вещами, которые имеют побочные эффекты. В большинстве случаев вы можете косвенно исправить:
string foo = Foo();
Debug.WriteLine(foo);
Теперь он вызывается в любом режиме.
Как я уже сказал, я не думаю, что в нашем коде есть какие-либо директивы прекомпилятора, условные атрибуты отладки и т. д. То же самое и с Debug.WriteLine. Но необходимы дополнительные исследования.
Вы можете попробовать отключить оптимизацию кода в настройках сборки. Какую фактическую ошибку вы получаете.
Еще вы можете выполнить компиляцию в режиме выпуска, но включить условие #Debug. Это будет обрабатывать случай, если вы используете Diagnostics.Debug и код в нем влияет на ваше приложение.
Debug.Assert(ImportantMethod());
У вас может быть какое-то состояние гонки, если вы не работаете с однопоточным кодом. Например, если какая-то часть вашей программы должна выполнить некоторые действия, прежде чем другие части смогут получить к ней доступ, она может выйти из строя в режиме выпуска просто потому, что к коду обращаются слишком рано. Однажды у нас была аналогичная проблема с некоторым кодом для мобильных телефонов, который нормально работал в эмуляторе, но на телефоне, который был медленнее, ситуация была совсем другой.
Вы пробовали включать файлы отладки? (PDBS)
Если вы перейдете в настройки проекта, а затем на вкладке компиляции выберите сборку выпуска в раскрывающемся списке вверху, затем выберите расширенные параметры компиляции внизу, обязательно установите для него ПОЛНУЮ отладочную информацию, а затем выполните повторное развертывание, вы должны Теперь получите более подробную информацию о причине сбоя.
Я видел время, которое вызывает проблемы между сборкой отладки и выпуска. Обычно сборка отладки выполняется медленнее, чем сборка выпуска. Возможно, вы захотите проверить критичный по времени участок вашего кода.
Вы, наверное, знаете это, но, переменные иногда инициализируются по-разному в сборках отладки и выпуска. Например. Я думаю, что переменные автоматически инициализируются в отладочных сборках VC6, это может скрыть проблемы, если вы что-то не инициализировали. Я также думаю, что массивы отладки могут использовать сторожевые байты в попытке указать на переполнение. Это тоже может привести к другому поведению.
Я бы поставил +1, если бы спрашивающий не указал, что использует управляемый код. В 9 случаях из 10, когда у меня возникала подобная проблема, она была на С ++, и это было потому, что я забыл правильно инициализировать что-то в .ctor. К счастью для меня, ни одна из этих ошибок так и не была реализована.
У меня была похожая проблема. Моя ситуация такая: Я определил некоторые функции отражения в библиотеке классов A. Затем я определил библиотеку пользовательских элементов управления WPF B, которая использует функции из библиотеки A. Затем я закодировал приложение, которое использует пользовательский элемент управления из библиотеки B и функции в библиотеке A. Когда я использовал отладочную версию библиотеки B, работает нормально. Но когда я использовал релизную версию библиотеки B, функции отражения не работали. Я также определил другие функции в библиотеке A. Кажется, проблемы вызывают только функции отражения. Не могу понять причину. Наконец, я сдался и переместил функции отражения из библиотеки A в библиотеку B. И это сработало.
В какой-то момент у меня была проблема с тем, что финализаторы сработали раньше, чем ожидалось, потому что я не полностью понимал взаимодействие между финализаторами, сборщиком мусора и тем, когда локальный объект считается собираемым (подсказка: это не закрывающая фигурная скобка блок). Если в вашем коде используются финализаторы, вы можете изучить GC.KeepAlive (). В следующем блоке:
void MyFunction()
{
Foo f = new Foo();
SomeFunction(f.SomeProp);
}
f получает право на финализацию еще до запуска SomeFunction()! Если финализатор сделает что-то вроде утилизации того, что раздал SomeProp, у вас могут возникнуть проблемы. Добавление вызова GC.KeepAlive(f) после вызова SomeFunction гарантирует, что f не будет иметь права на финализацию до завершения вызова KeepAlive().
Обновлено: после всего этого я забыл указать, что эта проблема была гораздо более выраженной при работе в режиме выпуска. Я не знаю, помещает ли сборка Debug неявные KeepAlives для локальных пользователей в конце функции в пользу отладчика, или сборка мусора просто менее агрессивна, или что-то еще, но в моем случае режим Release значительно усугубил эту проблему.
Решили проблему?
У меня такая же проблема, как и у вас.
Если я скомпилирую dll в отладке, все будет работать нормально.
Если я компилирую в выпуске, я получаю исключение с нулевой ссылкой.
Но если я включу некоторые строки, подобные приведенной выше, в вызов некоторых методов, исключение исчезнет даже в режиме выпуска:
System.Diagnostics.EventLog.WriteEntry ("блаблабла", "блаблабла")
Надеюсь, это вам поможет.
Убедитесь, что приложение строится в соответствии с правильной целевой платформой. Это может быть проблемой, особенно когда дело доходит до предоставления или использования библиотек DLL. Посмотрите в «Проект-> Свойства» и выберите вкладку «Сборка». Параметр «Целевая платформа» позволит вам выбрать любой процессор (по умолчанию), x86 или x64.
В моей конкретной ситуации я закончил тем, что настроил все проекты для сборки как x86.
Прежде всего извините за мой английский. Я знаю, что этот пост старый, но у меня такая же проблема, и я понимаю, что в режиме отладки сборка выполняется для 32-битная ОС, а режим выпуска по умолчанию - для 64 бит. Это делает DLL, созданную для 32-битной версии, не работающей в выпуске. Если вы перейдете в Свойства проекта -> построить, вы можете выбрать нужную архитектуру. У меня это работает.
В моем случае это было то, что мой проект потребителя DLL (в VS) имел конфигурацию x64, но решение было в любом процессоре. По какой-то причине при запуске приложения это не связано с моей x64 DLL. Я настроил приложение на платформу x64 явно, и все работало правильно.
Была такая же проблема с C# DLL, содержащей клиент WCF, предоставленный для нескольких клиентских приложений.
Выяснилось, что в клиентской библиотеке C# есть метод доступа к StackTrace для ведения журнала, который при компиляции в отладке отличается.
StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(2).GetMethod();
GetFrame(2) в выпуске не существовало. Более подробную информацию об этом можно найти здесь: Методы класса StackTrace не работают в режиме выпуска
Забавно, что клиент VB.NET пострадал, в то время как в другом клиенте C# .NET он работал правильно.
Надеюсь, поможет.
Вероятно, это не относится к исходному вопросу, но для всех, кто запускает приложение, которое использует
var isThisMyAssembly = System.Reflection.Assembly.GetCallingAssembly();
этот вызов может быть встроен в метод другой сборки во время выполнения и, следовательно, получить неожиданный результат (как указано в Документация MSDN).
Чтобы этого избежать, вы можете применить к своему методу MethodImplAttribute:
[MethodImpl(MethodImplOptions.NoInlining)]
void DoSomeThings()
{
var isThisMyAssembly = System.Reflection.Assembly.GetCallingAssembly();
//do stuff
}
или вы можете переключиться на использование Assembly.GetExecutingAssembly().
Было бы полезно дать некоторые подробности о проблеме, кроме общих: «она работает при отладке, но не в выпуске». Что такое «это», что «это»?