あれの開発記 27ページ目 バグ? [ColdFire V1]
投票感謝キャンペーンは以下のアドレスで行っています。
http://hamayan.blog.so-net.ne.jp/2008-09-01-2
なんかSilentCのポート番号の扱いにバグがあるかもしれない。
元々ポート番号は0~65535までの符号無し16bitの値を取るのだけれど、SilentCの場合はint型を使用している。
偶々なんだけれどポート番号40000をbindした相手先からパケットを送って、受け側ではこの様に処理してみた。
この中でr_port == 40000で引っ掛かってこの条件式は成立しなかった。そこでPrNumでr_portを表示させてみると(-25536)となってしまった。当然これでは一致しない。
元々このColdFireは32bitマイコンなのでint型も32bitと思われる(だよね)。だから正の整数の範囲に入っている40000はそのまま比較される筈。
ところがr_port = GetSenderPort( soc );の代入時には何処かで符号拡張が行われ、40000(0x9c40)は-25536として代入されてしまったのだろうと推測しております。
と言う訳で以下の様に直しました。
何故か
r_port = GetSenderPort( soc ) & 0xffff;
では(-25536)のままでした。
0xffffの扱いが気になったので、int型が32bitのBCC32で以下の実験を行ってみました。
結果は、
と、0xffffと0xffffffffはちゃんと区別してくれています。
何か間違っているのか?。実はint型は32bitではない?。
望洋さーん。
http://hamayan.blog.so-net.ne.jp/2008-09-01-2
なんかSilentCのポート番号の扱いにバグがあるかもしれない。
元々ポート番号は0~65535までの符号無し16bitの値を取るのだけれど、SilentCの場合はint型を使用している。
偶々なんだけれどポート番号40000をbindした相手先からパケットを送って、受け側ではこの様に処理してみた。
if( (len = RecvFrom( soc, 10 )) == (-1) ) break; else if( len > 0 ) { e_buf = GetReceiveBuffer( soc, 1 ); r_ip = GetSenderIP( soc ); r_port = GetSenderPort( soc ); if( r_ip == dip && r_port == 40000 ) { for( p = e_buf; len > 0; len-- ) { if( *p == 0x1b ) { MemoryFree( e_buf ); CloseSocket( soc ); return; } PrChar( *p++ ); } } else
この中でr_port == 40000で引っ掛かってこの条件式は成立しなかった。そこでPrNumでr_portを表示させてみると(-25536)となってしまった。当然これでは一致しない。
元々このColdFireは32bitマイコンなのでint型も32bitと思われる(だよね)。だから正の整数の範囲に入っている40000はそのまま比較される筈。
ところがr_port = GetSenderPort( soc );の代入時には何処かで符号拡張が行われ、40000(0x9c40)は-25536として代入されてしまったのだろうと推測しております。
と言う訳で以下の様に直しました。
r_port = GetSenderPort( soc ); if( r_ip == dip && (r_port & 0xffff) == 40000 )
何故か
r_port = GetSenderPort( soc ) & 0xffff;
では(-25536)のままでした。
0xffffの扱いが気になったので、int型が32bitのBCC32で以下の実験を行ってみました。
#includevoid main( void ) { printf( "0xffff=%d\n", 0xffff ); printf( "0x0ffff=%d\n", 0x0ffff ); printf( "0xffffffff=%d\n", 0xffffffff ); printf( "-1=%d\n", -1 ); }
結果は、
0xffff=65535 0x0ffff=65535 0xffffffff=-1 -1=-1
と、0xffffと0xffffffffはちゃんと区別してくれています。
何か間違っているのか?。実はint型は32bitではない?。
望洋さーん。
2008-09-02 20:47
nice!(0)
コメント(7)
トラックバック(0)
OS-1 プログラミングマニュアルによると、GetSenderPort( soc )が返すのは、intだそうです。これを r_port に代入すると r_port は、-25536 になります。
一方、 int 型の GetSenderPort( soc ) と int 型の 0xffff の論理積は、 int 型の -25536 のままで、これを r_port に代入すると -25536 になってしまいます。
(r_port & 0xffff) == 40000 が真になったことから、 r_port は long 型で、 0xffff も long 型として扱われたのではないかと推測します。
かといって、明示的なキャストや型指定定数などは記述できないようです。
すべて32-bitで書いてみてはどうでしょうか。
r_port = GetSenderPort( soc ) & 0x0000ffff;
by noritan (2008-09-03 08:55)
ああなるほど、明示的にffffの前に0を付ければ良いと。
by hamayan (2008-09-03 09:12)
と言うか、ちょっと焦点がずれそうなので補足しておくと、
まずbindする段階でもport番号はint型で扱われていますが、最終的にUDPヘッダーにコピーする所では符号無し16bitで扱われます。精度が落ちるのでもう元のデータが正なのか負なのか判らなくなり、CodeWarriorでは「本当にそんな代入して良いの?」と警告を受けるあれです。
逆に受けた符号無し16bit値をint型に何処かで変換していますが、その段階で符号拡張無しで変換してくれれば良いのですが、そうではないみたいなので、つまりユーザーはポート番号を-32768~32767の範囲で扱わなければならない。
「しかしこれはあれじゃあないですか?」と言う話です。
by hamayan (2008-09-03 09:33)
つまり、「そもそも GetSenderPort( soc ) が 16bit の int を返してくるところがおかしい」というわけですね。
> 符号無し16bit値をint型に何処かで変換しています
int 型は 16bit なので、拡張なんかせずに、そのままコピーしていると思います。
# あれ?違う話をしているのかな?
by noritan (2008-09-03 12:37)
そうですね、適切な表現としたらunsigned shortではないでしょうか。ポート番号は負の値をとらないですし。
または精度を落とさずにポート番号を収容できる32bit int。
それよりも、SilentCのint型は一体16bitなのでしょうか、それとも32bitなのでしょうか?。てっきり32bitだと思っていたのですが。
プログラミングマニュアルの言語仕様はまだ出来ていないらしく、判らないのです。みんな困らないのかな?。
by hamayan (2008-09-03 12:57)
PrHex(long)
PrHexWord(int)
PrHexByte(char)
と、並んでいるので、 int は、当然 16bit だと理解していました。
# もともとは、 S12NE64 という 16bit MCU 向けのインタプリタですから。
by noritan (2008-09-03 13:01)
ああナルホド、ライブラリから判断できるのか、、、。
てっきりコンピューターの自然な整数サイズだと思っていた。(※8bitは除く)
by hamayan (2008-09-03 13:07)