user2316502 user2316502 - 19 days ago 7
C# Question

Win32 DLL in C# Program AccessViolationException

So, I'm having the age old problem of "I changed my code and it didn't work, but then I changed it back and it still doesn't work". We have been working with DLLs as part of an assignment and the instructor gave us the code to play and record sound, which was supposed to be put into the DLL and then used in our own C# program. Yesterday, it worked fine, but then I was trying to figure out if some of my code was redundant, I managed to break it.

Upon calling the startup function

initDialog
from my main program I now get an
AccessViolationException
. I'm well aware that most of the time when you get this issue it is because you are trying to use something that was left uninitialized. However, I don't see anything that should cause this problem in my code, and the debugger doesn't really give me any hints as to what the cause is.

I'll post the code for my
initDialog
function and the variable declarations below and if necessary I can post more of the code later. The idea is I'm creating an invisible window to handle the messages I'm sending so that I don't have to deal with messages in 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);
}
}


In the main program I have this code:

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

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

Answer

I figured it out. The exception was generated by the line:

*pSaveBuffer = (PBYTE)malloc(1);

When I changed the buffer to be a double pointer into a single pointer I made the incorrect assumption that all I had to do was dereference it and then malloc the single pointer. However, I never malloced the single pointer so I could not dereference the double pointer. Adding this line solved the problem:

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