我有以下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
使用简单的.def文件:
LIBRARY MyLib
EXPORTS PrintMess
EXPORTS TestReturn
我正在从C#调用PrintMess
和TestReturn
:
[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);
}
我第一次运行它时,它在Console.ReadKey(true)
处暂停,我得到了预期的输出:
Printed from C#
Printed from assembly
Returned: 30
如果我在我的C#项目中进行了更改,请说TestReturn(30)
更改为TestReturn(50)
,那么它表现得很奇怪。该程序没有错误地终止,并且不会在Console.ReadKey(true)
暂停(它似乎甚至没有到达那一行),这是我的输出:
Printed from C#
Printed from assembly
我必须重建装配项目。具体来说,我必须重建,如果我做另一个常规版本,该程序继续行为不端。当我重建时,输出和行为将恢复正常并反映输出中的数字更改。我的猜测是Build和Rebuild之间的某些东西是不同的,它部分地破坏了DLL。
为什么我必须重建以及如何设置它以便我不必?
答案 0 :(得分:2)
@HansPassant最可能是正确的,但没有解释为什么你必须重建。 @jacobaloysious很接近。
VS正在使用所谓的“托管过程”来简化和隔离调试。当您从VS调试test.exe
时,实际上您正在调试test.vshost.exe
,它会加载您的exe。停止调试时,不会卸载主机可执行文件,因此您的实际可执行文件。当你构建你的代码而不改变任何东西时,VS实际上除了检查文件是否是最新的之外什么都不做。 VS认为,如果文件没有改变,那么就没有必要重新加载托管进程了。如果你重建,即使你没有更改任何代码,你真正的可执行文件也会被更新,这会强制主机进程终止并重新加载,以及你的真实可执行文件。
我认为,这个过程实际上是通过预加载汇编代码来加速调试的启动。您可以尝试在项目属性中关闭“启用Visual Studio托管过程”。之后,您应该看到您的项目按预期工作。
在你进一步行动之前,要意识到@HansPassant是正确的并且你有一个损坏的堆栈,随着时间的推移,你的项目将以意想不到的方式以最不愉快的方式以最不愉快的方式失败。在大多数情况下,您的应用程序将抛出没有意义的异常,在某些情况下,您的应用程序将会消失。