2008-12-15 74 views
13

将我们庞大的分布式系统部署到我们的客户之一后,我们遇到了意外错误。在调查过程中,我们将导致错误的程序集替换为添加了一些诊断代码的程序集。我们使用的dll是以调试模式构建的。突然它一切正常!当发布DLL不起作用但调试dll时

用发布版本(带有诊断代码)替换调试dll会再次崩溃。

我们的代码中没有预编译器指令,条件调试属性等。在两个不同的安装地点发现了这个问题,而在其他几个地方工作正常。

(该项目的C#和VB.NET的混合,在troublesom组装VB.NET ..,如果有什么差别)

所以,问题是:那你在做的情况下,喜欢这个?一般来说,原因是什么?欢迎任何有关调试此问题的建议。

+0

这可能有助于给出一些关于这个问题的细节,除了一般的“它在调试但不在发布中”。什么是“它”,什么是“它”? – Will 2008-12-15 13:53:59

+0

我还没有能够确定它,但它是一个空引用异常(所以这并不真正有帮助,对!)。 – 2008-12-15 14:22:27

+1

可能会与callstack一起。检查callstack是你应该做的第一件事情之一。 – Will 2008-12-15 15:10:32

回答

12

对于原因...以及某些症状的提示将有所帮助。一种可能性是你有代码到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"; 
    } 

在调试模式下编译它打印“我正在”;在RELEASE模式下编译它打印出“我坏了”。这听起来相似吗?检查你没有调用任何调试方法直接有副作用的东西。在大多数情况下,您可以通过间接方式修复:

string foo = Foo(); 
Debug.WriteLine(foo); 

现在它在任一模式下被调用。

+0

正如我所说,我不认为在我们的代码中有任何预编译器指令,条件调试属性等。 Debug.WriteLine也一样。但需要更多的调查。 – 2008-12-15 14:23:55

4

您可以尝试关闭生成设置中的优化代码。什么是你得到的实际错误。

你可以做的另一件事是在发布模式下编译,但启用#Debug条件。如果您使用Diagnostics.Debug和其中的代码会影响您的应用程序,这将处理这种情况。

4
Debug.Assert(ImportantMethod()); 
+0

另一个非常好的[Conditional(...)]示例。 – 2008-12-15 13:59:59

3

如果您不使用单线程代码,它可能是某种竞争条件。例如,如果程序的某些部分需要在其他部分访问之前执行某些操作,则可能会因为代码访问得太早而在发布模式下失败。我们曾经遇到类似的问题,其中一些手机代码在模拟器中运行良好,但在手机上速度较慢,结果完全不一样。

4

您是否尝试过包含调试文件?(pdbs)

如果你去你的项目设置,然后编译选项卡,选择你的发布版本在靠近顶部的下拉列表中,然后选择底部附近的高级编译选项,确保将其设置为创建FULL调试信息,然后重新部署,您现在应该了解有关崩溃原因的更多详细信息。

4

我见过调试和发布构建之间的时间问题。通常,调试版本比发布版本运行速度慢。您可能需要检查代码的时间关键部分。

0

您可能知道这一点,但是, 变量有时在调试和发布版本中的初始化方式有所不同。 例如 我认为变量在VC6调试版本中是自动初始化的,如果你没有初始化某些东西,这可以隐藏问题。我也认为调试数组可能会使用sentry字节来试图指示超限。这也可能导致不同的行为。

0

我有类似的问题。我的情况如下: 我在类库A中定义了一些反射函数,然后我定义了一个WPF用户控件库B,它使用库A中的函数。然后我编写了一个应用程序,它使用库B中的用户控件和函数在库A.当我使用库B的调试版本时,它工作正常。但是当我使用库B的发布版时,反射功能不起作用。我还定义了库A中的其他函数。似乎只有反射函数会造成麻烦。我无法弄清楚原因。最后,我放弃并将反射函数从库A移动到库B,并且工作。

1

由于我没有完全理解终结器,垃圾回收器,以及本地对象被认为是可收集的时间,所以终结器的运行速度比预期的要快,因此我遇到了一个问题(提示:它不在关闭块的大括号)。如果你的代码使用终结器,你可能希望看看GC.KeepAlive()。在下面的块:

void MyFunction() 
{ 
    Foo f = new Foo(); 
    SomeFunction(f.SomeProp); 
} 

f就符合定稿SomeFunction()运行之前!如果终结者做了类似处置任何事情,你可能会陷入困境。在致电SomeFunction之后,拨打电话GC.KeepAlive(f)确保f在拨打电话KeepAlive()之后才可以结束。

编辑:毕竟,我忘了指出这个问题在发布模式下运行时更为明显。我不知道Debug构建是否为了调试器的好处而将隐式的KeepAlives作为本地函数的末尾,或者如果垃圾收集不那么积极,或者什么,但是在我的情况下,Release模式加剧了这个问题。

0

你解决了你的问题吗?
我和你有同样的问题。
如果我在调试中编译dll,一切正常。
如果我在版本中编译我得到一个空引用异常。
但是,如果我包括像上面的一个,在一些方法调用一些线条,异常甚至在释放模式了:
System.Diagnostics.EventLog.WriteEntry(“blablabla”,“blablabla”)

。希望帮助你。

1

确保应用程序在正确的平台目标下生成。这可能是一个问题,特别是在提供或使用DLL时。在“Project-> Properties”下查找并选择“Build”选项卡。平台目标选项将允许您在任何CPU(默认),x86或x64之间进行选择。

1

首先抱歉我的英语。我知道这个帖子是旧的,但我有同样的问题,我意识到,在调试模式下构建为32位操作系统,并释放模式为64位默认情况下。这使得dll的32位无法正常工作。如果你去项目属性 - >建立你可以选择你想要的架构。这对我有用。 再见。

0

在我的情况是,我的DLL消费者项目(在VS)有x64配置,但解决方案是在任何CPU。 由于某些原因,在运行应用程序时,这并未挂钩我的x64 DLL。 我将应用程序配置为x64显式平台,并且一切正常。