2016-11-12 2 views
-2

Итак, у меня возникла старая проблема: «Я изменил свой код, и он не сработал, но потом я изменил его, и он все еще не работает». Мы работали с DLL как часть задания, и инструктор дал нам код для воспроизведения и записи звука, который должен был быть помещен в DLL, а затем использован в нашей собственной программе на C#. Вчера это работало нормально, но потом я пытался выяснить, был ли лишний код моего кода лишним, мне удалось его сломать.Win32 DLL в C# Program AccessViolationException

После вызова функции запуска 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??? 
    } 
+1

Пара ключевых навыков, необходимых вам, чтобы научиться двигаться вперед. Прежде всего, это, безусловно, источник контроля, * очень важно, чтобы восстановить свою программу в ее первоначально работающее состояние. И вам нужно научиться отлаживать собственный код, чтобы вы могли видеть, какой оператор генерировал исключение. Все это хорошо видно в существующем Q + A на этом сайте. И, возможно, немного подумайте о мудрости выделения 1-байтового буфера сохранения и регистрации класса окна более одного раза. –

+0

Помимо размышлений у Ганса, мне было интересно, что вы ожидаете от цикла с концом. – rene

+0

@rene Цикл while предназначен для получения и обработки сообщений в WndProc. В этом случае я использую его для получения сообщений, относящихся к функциям воспроизведения и записи. – user2316502

ответ

-1

Я понял это. Исключение было сгенерировано линии:

*pSaveBuffer = (PBYTE)malloc(1); 

Когда я изменил буфер быть двойной указатель в один указатель я сделал неверное предположение, что все, что я должен был сделать разыменования его, а затем таНос единый указатель. Тем не менее, я никогда не переводил один указатель, поэтому я не мог разыменовать двойной указатель. Добавление этой линии решает проблему:

pSaveBuffer = (PBYTE*)malloc(1); //this line 
*pSaveBuffer = (PBYTE)malloc(1); 
Смежные вопросы