为什么我必须重建一个未更改的项目?

Cor*_*urn 7 c# interop masm visual-studio-2010

我有以下MASM代码:

.386
.model flat, stdcall
option casemap :none

include \masm32\include\masm32rt.inc

.data
    NewLine db  13, 10, 0
.code

LibMain proc instance:dword,reason:dword,unused:dword 
    mov     eax, 1
    ret
LibMain endp

PrintMess proc
    print "Printed from assembly"
    invoke StdOut, addr NewLine
    ret
PrintMess endp

TestReturn proc number:dword
    mov     eax, number
    ret
TestReturn endp

End LibMain
Run Code Online (Sandbox Code Playgroud)

使用简单的.def文件:

LIBRARY MyLib
EXPORTS PrintMess
EXPORTS TestReturn
Run Code Online (Sandbox Code Playgroud)

我打电话PrintMess,并TestReturn从C#这样:

[DllImport("MyLib")]
static extern void PrintMess();

[DllImport("MyLib")]
static extern int TestReturn(int num);

static void Main(string[] args) {
    Console.WriteLine("Printed from C#");

    PrintMess();

    int value = TestReturn(30);
    Console.WriteLine("Returned: " + value);

    Console.ReadKey(true);
}
Run Code Online (Sandbox Code Playgroud)

我第一次运行它,它暂停了Console.ReadKey(true),我得到了预期的输出:

Printed from C#
Printed from assembly
Returned: 30
Run Code Online (Sandbox Code Playgroud)

如果我然后在我的C#项目中进行更改,请TestReturn(30)更改为TestReturn(50)然后它表现得很奇怪.程序终止没有错误,并且不会暂停Console.ReadKey(true)(似乎它甚至没有到达那一行)这是我的输出:

Printed from C#
Printed from assembly
Run Code Online (Sandbox Code Playgroud)

我必须重建装配项目.具体来说,我必须重建,如果我做另一个常规版本,该程序继续行为不端.当我重建时,输出和行为将恢复正常并反映输出中的数字更改.我的猜测是,Build和Rebuild之间的某些东西是不同的,它部分地打破了DLL.

为什么我必须重建以及如何设置它以便我不需要?

Erd*_*tur 2

@HansPassant 很可能是正确的,但没有解释为什么你必须重建。@jacobaloysious 很接近。

VS 使用所谓的“托管进程”来简化和隔离调试。当您test.exe从 VS 进行调试时,实际上您正在调试test.vshost.exe,它会加载您的 exe。当您停止调试时,主机可执行文件不会被卸载,因此您真正的可执行文件。当您在不更改任何内容的情况下构建代码时,VS 实际上除了检查文件是否是最新的之外什么也不做。VS认为,如果文件没有改变,那么就不需要重新加载托管进程。如果您重建,即使您没有更改任何代码,您真正的可执行文件也会更新,这会强制终止并重新加载主机进程以及您真正的可执行文件。

我认为,这个过程实际上是通过预加载汇编代码来加速调试的启动。您可以尝试在项目属性中关闭“启用 Visual Studio 托管进程”。之后,您应该会看到您的项目按预期工作。

在继续前进之前,请意识到@HansPassant是正确的,并且您的堆栈已损坏,并且随着时间的推移,您的项目将在意想不到的时间以意想不到的方式以最令人不愉快的方式失败。在大多数情况下,您的应用程序将抛出没有意义的异常,并且在某些情况下,您的应用程序将消失。