我有一个基本上做三件事的应用程序:
每个用户发生280次,并且所有记录都保存在每个用户的目录中。但是,在程序的最后18次运行中有2次,它从模块ntdll.dll中的代码c0000005(被描述为访问冲突)的未处理异常中崩溃。我正在使用的唯一非托管api调用是来自winmm.dll的mciSendString来获取wav文件的持续时间并进行录制。使用WindowsMediaPlayer实例进行播放。
崩溃似乎是随机的,两者都发生在同一台机器上(正在使用3台)。这些是我的问题:ntdll.dll真的是异常的来源吗?我是否正确理解访问冲突是无效的内存访问?如果在.NET虚拟机中运行C#程序会怎么样?
根据请求,这里是一个我调用mciSendString
的类public class JE_SR
{
[DllImport("winmm.dll", EntryPoint = "mciSendStringA",
CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern uint mciSendString(string lpstrCommand,
string lpstrReturnString, int uReturnLength, int hwndCallback);
[DllImport("winmm.dll", CharSet = CharSet.Auto)]
private static extern int mciGetErrorString(uint errorCode,
StringBuilder errorText, int errorTextSize);
private static bool recording = false;
public static uint lastResult;
public static void startRecording()
{
if (recording)
{
return;
}
tryMCISendString("open new Type waveaudio Alias recsound", "", 0, 0);
tryMCISendString("record recsound", "", 0, 0);
recording = true;
}
public static void stopRecording(string file)
{
if (!recording)
{
return;
}
if (!file.Equals(""))
{
tryMCISendString("save recsound " + file, "", 0, 0);
tryMCISendString("close recsound ", "", 0, 0);
}
else
{
tryMCISendString("close all", "", 0, 0);
}
recording = false;
}
public static void tryMCISendString(string lpstrCommand,
string lpstrReturnString, int uReturnLength, int hwndCallback)
{
lastResult = mciSendString(lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback);
StringBuilder error = new StringBuilder(256);
if(lastResult != 0)
{
mciGetErrorString(lastResult, error, error.Length);
JE_Log.logMessage("MCIERROR(JE_SR): " + error.ToString());
}
}
}
请告诉我是否还有其他相关细节......
答案 0 :(得分:2)
一个问题是:
private static extern uint mciSendString(string lpstrCommand,
string lpstrReturnString, int uReturnLength, int hwndCallback);
最后一个值应为IntPtr
。否则它不会在64位运行时工作,并且可能会有东西踩到堆栈上。将其更改为IntPtr
并传递“IntPtr.Zero”。
此外,lpstrReturnString
参数用于将指针传递给将接收返回数据的缓冲区。在这里传递一个空字符串是个坏主意,因为mciReturnString
可能会尝试在该字符串中存储数据。这可能会给你一个访问冲突,或者更糟糕的是,覆盖一些关键的东西。如果您不需要返回错误信息,请将其更改为IntPtr
并传递IntPtr.Zero
,或使用StringBuilder
。有关正确的定义,请参阅http://www.pinvoke.net/default.aspx/winmm.mcisendstring。
而且,是的,ntdll.dll成为异常的来源是完全合理的,因为winmm.dll中的函数可能会调用ntdll.dll中的函数。正如其他人所说,你需要一个原生的堆栈跟踪来确切地看到发生了什么。