【问题标题】:Win32 DLL in C# Program AccessViolationExceptionC# 程序 AccessViolationException 中的 Win32 DLL
【发布时间】:2016-11-12 09:29:22
【问题描述】:

所以,我遇到了“我更改了我的代码但它不起作用,但后来我将它改回来但它仍然不起作用”的老问题。作为作业的一部分,我们一直在使用 DLL,讲师给了我们播放和录制声音的代码,这些代码应该被放入 DLL,然后在我们自己的 C# 程序中使用。昨天,它运行良好,但后来我试图弄清楚我的某些代码是否是多余的,我设法破坏了它。

从我的主程序调用启动函数initDialog 后,我现在得到一个AccessViolationException。我很清楚,大多数时候你遇到这个问题是因为你试图使用一些未初始化的东西。但是,我没有在我的代码中看到任何应该导致此问题的内容,并且调试器并没有真正给我任何关于原因的提示。

我将在下面发布我的initDialog 函数和变量声明的代码,如有必要,我可以稍后发布更多代码。我的想法是创建一个不可见的窗口来处理我发送的消息,这样我就不必在 C# 中处理消息。

    static WAVEFORMATEX waveform;
    static PBYTE*    pSaveBuffer;
    static BOOL      bRecording = FALSE, bPlaying = FALSE, bReverse = FALSE,
                     bPaused = FALSE, bEnding = FALSE, bTerminating = FALSE;
    static DWORD     dwDataLength, dwRepetitions = 1;
    static HWAVEIN   hWaveIn;
    static HWAVEOUT  hWaveOut;
    static PBYTE     pBuffer1, pBuffer2, pNewBuffer;
    static PWAVEHDR  pWaveHdr1, pWaveHdr2;
    static HWND      myHwnd;
    static TCHAR     szAppName[] = TEXT("Record/Play"),
    static HINSTANCE hInst;

    __declspec(dllexport) void CALLBACK initDialog() {
        WNDCLASS wndclass;
        MSG msg;

        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc = WinProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInst;
        wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;

        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("This program requires Windows 95/98/NT"),
            szAppName, MB_ICONERROR);
            return;
        }

        myHwnd = CreateWindow(szAppName, TEXT("Record/Play"), WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, hInst, NULL);

        // Allocate memory for wave header

        pWaveHdr1 = (PWAVEHDR)malloc(sizeof(WAVEHDR));
        pWaveHdr2 = (PWAVEHDR)malloc(sizeof(WAVEHDR));

        // Allocate memory for save buffer

        *pSaveBuffer = (PBYTE)malloc(1);

        while(GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

在主程序中我有这个代码:

    [DllImport("RecordDll.dll", CharSet = CharSet.Auto)]
    public static extern int initDialog();

    public PlayForm()
    {
        InitializeComponent();
        this.Show();
        initDialog();//AccessViolationException???
    }

【问题讨论】:

  • 您需要学习一些关键技能才能取得成功。首先当然是源代码控制,非常能够将您的程序恢复到其最初的工作状态。而且您需要学习如何调试本机代码,以便查看生成异常的语句。本网站现有的 Q+A 很好地涵盖了所有内容。并且也许思考一下分配一个 1 字节的保存缓冲区并多次注册一个窗口类的智慧。
  • 除了 Hans 的思考之外,我想知道你期望在最后使用 while 循环会发生什么。
  • @rene while 循环用于获取和处理 WndProc 中的消息。在这种情况下,我使用它来获取与播放和录制功能有关的消息。

标签: c# winapi dll


【解决方案1】:

我想通了。异常是由以下行生成的:

*pSaveBuffer = (PBYTE)malloc(1);

当我将缓冲区从双指针更改为单指针时,我做出了错误的假设,即我所要做的就是取消引用它,然后对单指针进行 malloc。但是,我从未分配过单指针,因此无法取消对双指针的引用。添加此行解决了问题:

pSaveBuffer = (PBYTE*)malloc(1); //this line
*pSaveBuffer = (PBYTE)malloc(1);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多