CreateFile with Serial communication has access violation
I've been trying convert a serial communication library to Win32 for use with talking to hardware. I thought that I had properly used the CreateFile function to open a connection, but I'm having issues with access violations in the main function of the test program I wrote. initCSACConnection gets the HANDLE and passes it to main, but the main function fails when trying to assign the value to the local variable there. The error message is "0xC0000005: Access violation writing location 0xfffffff9." I do not understand why I am getting this error here, I am only giving it a void*.
int main ( int argc, char **argv )
{
HANDLE csacConnection;
csacConnection = initCSACConnection("COM3");
return 0;
}
HANDLE initCSACConnection(char* port)
{
HANDLE portDescriptor;
portDescriptor = init_port(port, SERIAL_BAUD, "8N1");
return portDescriptor;
}
HANDLE init_port(char *port, int baud, char *control)
{
HANDLE portDescriptor;
portDescriptor = CreateFil开发者_如何学运维e(port, GENERIC_READ | GENERIC_WRITE, 0,
0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if ( portDescriptor == INVALID_HANDLE_VALUE )
{
perror("CreateFile") ;
exit( 9 ) ;
}
return portDescriptor;
}
You might start by making the code const
-correct, the Windows header files already are.
Then, also check the returned HANDLE
against NULL
. This shouldn't be necessary, but it's just good practice since NULL
is not a valid handle value on Win32 (0
is a valid POSIX fd however).
Check your UNICODE setting or call CreateFileA
explicitly.
Finally, make sure STRICT
is enabled. There shouldn't be any void*
anywhere in the code you've shown.
And just for fun, print out the handle returned from CreateFile
, so you can make sure it isn't being corrupted on return from your helper functions (calling convention mismatch could do that).
It turns out Hans is on the right track. I had extra code to attempt to modify the properties of the connection. I had commented out the SetCommState command at the end (to reduce the size and clutter of my initial post), thinking that would remove any issues as the rest of the code only modified the DCB. After reading Hans' comment, I commented out everything after the CreateFile command and it worked fine. Here is the entirety of init_port. It allows initCSACConnection to run correctly, but results in an access violation when main tries to assign the returned value to csacConnection.
HANDLE init_port(char *port, int baud, char *control)
{
HANDLE portDescriptor;
DCB t;
int bit, stop ;
char par ;
portDescriptor = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0,
0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if ( portDescriptor == INVALID_HANDLE_VALUE )
{
perror("CreateFile") ;
exit( 9 ) ;
}
/* Strip the control parameters from the control string */
sscanf_s( control, "%1d%1c%1d", &bit, &par, &stop ) ;
/* Read in the current port attributes */
FillMemory(&t, sizeof(t), 0);
if ( GetCommState(portDescriptor, &t) == 0 )
{
perror("GetCommState") ;
printf ("opened port:(%s) descriptor:%d speed:%d c:%1d%c%1d\n",
port, portDescriptor, baud, bit, par, stop );
exit( 2 ) ;
}
/* Set the # bits, parity and stop bits */
if ( (bit < 5) || (bit > 8) )
{
fprintf(stderr, "Invalid character bit size:%d [5-8]\n",bit ) ;
exit( 2 ) ;
}
if ( par == 'E' || par == 'e' )
{
t.Parity = EVENPARITY ; /* Even parity */
t.fParity = FALSE ; /* Enable parity check */
}
else if ( par == 'O' || par == 'o' )
{
t.Parity = ODDPARITY ; /* Odd parity */
t.fParity = TRUE ; /* Enable parity check */
} else {
t.fParity = FALSE;
}
if (stop == 1)
t.StopBits = ONESTOPBIT;
else if (stop == 2)
t.StopBits = TWOSTOPBITS ; /* Two stop bits */
/* Set the baud rate */
switch(baud)
{
case 1200:
t.BaudRate = CBR_1200 ;
break;
case 2400:
t.BaudRate = CBR_2400 ;
break;
case 4800:
t.BaudRate = CBR_4800 ;
break;
case 9600:
t.BaudRate = CBR_9600 ;
break;
case 19200:
t.BaudRate = CBR_19200;
break;
case 38400:
t.BaudRate = CBR_38400;
break;
case 57600:
t.BaudRate = CBR_57600;
break;
case 115200:
t.BaudRate = CBR_115200;
break;
case 256000:
t.BaudRate = CBR_256000;
break;
}
if ( SetCommState(portDescriptor, &t) == 0 )
{
perror("SetCommState") ;
exit( 2 ) ;
}
return portDescriptor;
}
精彩评论