不覚にも初歩的なミスになかなか気づかなかった。

高木です。こんばんは。

金曜日のことです。
シリアルポートから受信したデータを解析して、データを取り出すという、まあよくある処理を書いていました。

大して難しい内容でもないので、気楽に取り組んでいたのですが、意外なところで手こずることになってしまいました。
まったくもって不覚としかいいようがありません。

何をやっていたかをもう少し詳しく書きたいと思います。

基本的にはCのコードなのですが、Tclをライブラリとして使ってシリアル通信を行っていました。
Tclを使った理由はいろいろありますが、それは本質ではないのでここでは触れないことにします。

シリアル通信ですので、チェックサムが付加されているのが普通ですね。
今回も例に漏れずチェックサムが付加されていました。

受信したデータのチェックサムを計算して、パケットにASCIIで埋め込まれているチェックサムと比較します。
すると、なぜか毎回チェックサムが一致しないというエラーが発生してしまうのです。

「おかしいな」と思っていろいろ確認しましたが、間違いが見つかりません。
計算ロジックのケアレスミスがあるかもしれないので確認しましたが、問題ありません。
受信データは1つのパケットをヘッダ、データ、フッターの3つに分けて読み込んでから再結合しているので、もしかすると再結合時に過不足があったかもしれないと思って確認しましたが、やはり問題ありません。

チェックサムが一致しない状況にも傾向があり、なぜか毎回3だけ小さい計算結果になってしまうのです。
なので、チェックサムを計算する範囲を間違えたのかと考えていました。
ドキュメントも何度も読み返しましたが間違いは見当たりません。

よく分からなかったのでしばらく放置していました。
その後、打合せやらがあってある程度時間が経過しました。
帰り際、「もしかして?」とある考えが閃きました。

確かめてみると案の定そうでした。
受信データのキャリッジリターン(0x0d)がラインフィード(0x0a)に変換されてしまっていました。
だから、0x0d – 0x0a = 3だけ計算結果がずれていたのです。

こんなテキストモードとバイナリモードの違いのような初歩的なミスは本来なら犯しませんし、仮にやってしまってもすぐに気づきます。
しかし、今回なかなかミスに気づきにくかったのは次のような理由からです。

  1. 送信にも同じチェックサム計算関数を使っていたが問題なかった。
  2. 受信を行う部分のコードを書いてから、ある程度時間が経過していた。
  3. fconfigureコマンドで-encoding binaryを指定していた。

このうち、上記の1.と2.は大したことではありません。
一番厄介だったのが3.です。
ここでbinaryを指定していたので、改行文字の問題は起きないだろうと高をくくっていたのです。

しかし、-encodingとあるように、文字通り解釈すれば改行文字に関するオプションではありません。
改行文字を変換することなくそのままにしておくには、-translation binaryを指定しないといけないのです。

というわけで、今回は恥をしのんで、こんな初歩的なミスを犯した体験をブログに書いてみました。
このブログを読んでいる皆さんは、決してこんなくだらないミスを犯さないでくださいね。