VS2005 RS-232C バグの件

igoten

2010年02月17日 17:42



これはソフトウェアーの純技術的なことなので
殆どの人はスルーでお願いします。
私のホームページから回って来られた方いらっしゃい。

VB2005でRS-232Cの受信のサンプルコードを書いた。

    C#コード
  private void SerialPort1_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
//データ受信用のバイト配列
byte[] inByte = new byte[serialPort1.BytesToRead];
//データの読み込み
serialPort1.Read(inByte, 0, serialPort1.BytesToRead);
  VB2005コード
Private Sub SerialPort1_DataReceived(ByVal sender As Object, _
ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
Handles SerialPort1.DataReceived
'データ受信用のバイト配列
Dim inByte(SerialPort1.BytesToRead - 1) As Byte
'データの読み込み
SerialPort1.Read(inByte, 0, SerialPort1.BytesToRead)

このたった2行のコードの中にバグが潜んでいた。
さてどこでしょうか?

serialPort1.BytesToReadはバッファの状態を読んでその時の受信データの 長さをByte単位で返すのであるが、実はこのC#とVB2005のコードは この長さを2度読みに行っている。
そしてこれが問題なのだ。
すなわち一度目の配列を確保する為に読みに行った時と、実際に serialPort1.BytesToReadで データを読みに行った時とで返す値が違う可能性があるのだ。

普通のソフトでは考えられないのであるが、RS-232Cの場合は十分考えられる。
次から次にデータが受信されるので配列を確保している間に次のデータを受信して しまうのだ。
そしてあの恐ろしいエラーが出る「配列の長さが範囲を超えている...」と。
これを解決するためには一回だけ読みに行けばよいのである。

書き直されたコード
    C#コード
   int dataLength = serialPort1.BytesToRead;
//データ受信用のバイト配列
byte[] inByte = new byte[dataLength];
//データの読み込み
serialPort1.Read(inByte, 0, dataLength);
  VB2005コード
Dim dataLength as Integer = SerialPort1.BytesToRead
'データ受信用のバイト配列
Dim inByte(dataLength - 1) As Byte
'データの読み込み
SerialPort1.Read(inByte, 0, dataLength)
とすればいいのです。
掲示板に投稿してくれた「たかさん」ごめんなさい。
と言ってもこんな所は読まないか。

関連記事