Just nu i M3-nätverket
Gå till innehåll

Windows seriell kommunikation = buggigt


dllg

Rekommendera Poster

Hej,

 

Jag har suttit en hel del och kodat på olika program som kommunicerar med grejer genom serieporten. Jag har upptäckt diverse konstigheter när jag använder windows färdiga funktioner för seriekommunikation. Nästan exakt samma funktioner finns i linux och de fungerar utmärkt!

 

Ex. - Ta emot data (linux) - fungerar

bool receive(int size){
 int n;

 n = read(hComPort, receivedData, size);

 if (n==0)
   return false;

 receivedData[n] = '\0';
 return true;
}

Ex. - Ta emot data (windows) - fungerar inte!

bool receive(int size){
 DWORD dwBytesTransferred;

 if (!ReadFile(hComPort, &receivedData, size, &dwBytesTransferred, 0))
   return false;

 if (dwBytesTransferred==0)
   return false;

 receivedData[dwBytesTransferred] = '\0';
 return true;
}

 

Om jag använder denna funktion i windows händer diverse skumma saker. Plötsligt får den för sig att det är "Access violation" att titta på dwBytesTransferred och ibland hoppar programpekaren plötsligt upp nånstans i minnet som får programmet att krascha.

 

Jag kom då på att man kanske inte kan låta ReadFile läsa direkt antal data utan låta den läsa 1 data i taget:

bool receive(int size){
 int i = -1;
 UInt8 r;

 do{
   // Read the data from the serial port.
   if (!ReadFile (hComPort, &r, 1, &dwBytesTransferred, 0))
     return false;

   //If you received anything
   if (dwBytesTransferred)
     //Put the received byte in a data-list
     receivedData[++i] = r;

 }while(dwBytesTransferred == 1 && i<(size-1) && r!='\r' && r!='\n');

 if (i == -1)
   return false;

 //Set stop mark on string
 receivedData[++i] = '\0';

 return true;
}

Denna kod fungerar perfekt. Men det jag undrar är om någon annan har stött på detta problem förut? Det är ju rätt dåligt av MS att tillhandaha buggiga funktioner. Det tog många dagar innan jag insåg att det inte var fel på min kod utan att det var windows som inte fungerade som det skulle...

 

/Daniel

 

[inlägget ändrat 2003-01-16 11:58:26 av dllg]

[inlägget ändrat 2003-01-16 12:12:47 av dllg]

Länk till kommentar
Dela på andra webbplatser

Jag är väldigt säker på att det inte finns något sådant fel i just de där funktionerna i någon windows-version.

 

Var har du deklarerat/allokerat "receivedData" och som vad och hur stor?

 

Tittar man på koden så ser det ut som om den i linuxfallet vore heap-allokerad och i windows-fallet ligger på stacken, är det verkligen så?

Om inte så kommer ju det första fallet (i windows-version) att skriva det den läser till pekaren som pekar på ditt allokerade minne och där lär det inte få plats mer än 4 bytes innan du får ett access vio.

 

 

Länk till kommentar
Dela på andra webbplatser

Litet förtydligande som förvisso inte pratar serieport men det gör ingen skillnad.

 

Ett litet program som förväntar sig ett filnamn som första argument (en existerande fil, annars lär det krascha, ingen felkontroll här inte :-):

 

#include <windows.h>

int main(int argc, char **argv) {
char *buffer=malloc(1000);
HANDLE file=CreateFile(argv[1], FILE_READ_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
DWORD bytesRead=0;

ReadFile(file, buffer, 20, &bytesRead, 0);
buffer[bytesRead]=0;
CloseHandle(file);
}

 

Ovanstående kommer att fungera (om man ger den rätt argument och så).

 

#include <windows.h>

int main(int argc, char **argv) {
char *buffer=malloc(1000);
HANDLE file=CreateFile(argv[1], FILE_READ_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
DWORD bytesRead=0;

ReadFile(file, &buffer, 20, &bytesRead, 0);
buffer[bytesRead]=0;
CloseHandle(file);
}

 

Koden ovan borde få ett Access Violation (om det finns mer än 4 tecken i filen) eftersom den försöker lagra tecknen i adressen för pekaren (skillnaden är en '&').

[inlägget ändrat 2003-01-16 12:53:51 av fhe]

Länk till kommentar
Dela på andra webbplatser

> Det är ju rätt dåligt av MS att tillhandaha buggiga

> funktioner. Det tog många dagar innan jag insåg

> att det inte var fel på min kod utan att det var

> windows som inte fungerade som det skulle...

 

 

Allt tyder på att felet är DITT. Du redovisar inte ett exempel som går att reproducera, inte heller berättar du var du får access violation. Jag är övertygad om att problemet finns i din kod, inte i ReadFile.

 

Ett uppenbart fel är som "fhe" skriver att du som argument till ReadFile anger adressen till pekaren till en buffert istället för pekaren till en buffert.

 

Var lite paranoid mot din egen kod istället för att beskylla kod som körs med gott resultat på miljontals datorer varje dag.

 

Länk till kommentar
Dela på andra webbplatser

Ursäkta!

 

Jag inser nu mitt misstag, men det känns hur som helst lättare att använda funktionerna i linux.

 

Bra att det finns folk som kan sina saker!

 

/Daniel

 

Länk till kommentar
Dela på andra webbplatser

Ursäkta!

 

Äsch, det var ju för att du ville ha svar på vad du gjorde för fel som du frågade (för jag misstänker att det var för att du tog för givet att det faktiskt skulle fungera som du ställde frågan :-).

Jag vet inte hur många gånger jag varit övertygad om att det varit en bugg i win32 som orsakat mina fel. Ibland har man rätt men visst har jag haft fel också, sånt händer.

 

Angående Win32 vs linux så håller jag nästan med dig, win32-api:erna har sina fördelar iom att de är designade för lite fler varianter, men visst hade det varit underbart om de hade sett ut precis som resten av världens api:er.

Vore jag i din situation (och det har jag varit några gånger) så skulle jag göra en c++-klass eller motsvarande som har metoderna recv, send oc andra som man kan vilja använda när man pratar med en serieport, därefter skulle jag implementera den för Windows och för Linux och låta programmet i övrigt vara lyckligt ovetande om de OS-specifika grejjerna.

 

Lycka till.

 

[inlägget ändrat 2003-01-16 22:09:13 av fhe]

Länk till kommentar
Dela på andra webbplatser

Arkiverat

Det här ämnet är nu arkiverat och är stängt för ytterligare svar.

×
×
  • Skapa nytt...