アカウント名:
パスワード:
ゼロ除算の結果は未定義だから、例外投げて死のうが何らかのデフォルト値を返そうがコンピューターが爆発しようが任意コードが実行されようが鼻から悪魔が出ようが仕様上は何の問題もない。チェックが不要になるわけではないが。むしろ例外が投げられると期待してチェックをサボってはいけない(実際にx86に慣れたプログラマーがARMデバイスでよく踏む罠)。
> 逆に、符号付整数加算はオーバフロー例外投げることがありますので、> 通常は符号なし整数加算に変換されます
符号付整数加算がオーバーフロー起こしたときの動作も未定義ですよ。だから別に変換しなくても(例外投げて死んでも)規格上は問題ないです。例外投げて死んでくれれば整数オーバーフロー系のセキュリティホールはだいぶ減らせると思うんですけどねえ。
組み込みで例外を起こそうとしてゼロ除算をしたら、例外起きず結果が0になって困ったことがあった。
組み込みだと*((int*)0)=0とかも大丈夫だったりするからなぁ…# そもそも例外機構が存在するかどうかも怪しい世界
まあ0番地はブート用のROMだったりRAMだったりすることも多いので、0番地アクセスを禁止されると困るわけですが。
ちなみに、わたしが普段使っているコンパイラはゼロ除算は被除数がそのまま返ります。つまり1で割ったのと同じ結果ですね。
> 組み込みだと*((int*)0)=0とかも大丈夫だったりするからなぁ…
ちなみにCortex-M向けのgccで上記のコードを書くと、実行時にHardFaultが起きるようにコンパイラが故意に未定義命令を吐いてくれたりします。一方で、*((int*)p)=0;と書いてもpの値をチェックしてくれるわけではないので、0を渡すと通ってしまうんですけど。
いいなあ、除算命令あるんだ。
# 8bitPICとか、普通に乗除算命令とかないですよ。# Cで使うと関数を作ってくれます。
## この手のMCUを使うと、C言語の標準に強烈な不満を感じます。## 8bit演算しかもってないのにinteger promotionとかアホかと。## まあ、intを8bitにするって手はあるけどsizeof(short)>sizeof(int)って不都合起きそう。
8ビットCPUのCで割り込み処理かいて単なる演算なのに関数よばれたりするけどその関数が再入可能でないので、動作が不安定なったり暴走したり、それに気が付かず延々とデバグしてた人いたな
未定義なら定義する方法が提供されていれば解決するのかな。
仕様上未定義ということは、コンパイラを実装する人が決めていいってことですよ。
仕様上で定義するには、C規格を改訂すればいいのです。
C言語の思想的に、そういう最適化の足かせになるような改訂を受理することはまずないと思うけどね。ゼロ除算が仕様上未定義だから、コンパイラは除数がゼロになることは絶対にないと決めつけて最適化を行うことができる。同様に配列の範囲外へアクセスしたときの結果が未定義だから、境界チェックを省略できる。
C99とか見てると、未定義動作はなるべく減らしたいなぁという意志が感じられなくもないですけどね。
> 実際にx86に慣れたプログラマーがARMデバイスでよく踏む罠 ノシ踏みましたよ。例外発生が常識だと思ってました…
戻り値が未定義なだけで、例外が発生するとか定義されているのでは?もちろん、爆発はしない。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
192.168.0.1は、私が使っている IPアドレスですので勝手に使わないでください --- ある通りすがり
C言語なら (スコア:1)
ゼロ除算の結果は未定義だから、例外投げて死のうが何らかのデフォルト値を返そうがコンピューターが爆発しようが任意コードが実行されようが鼻から悪魔が出ようが仕様上は何の問題もない。チェックが不要になるわけではないが。むしろ例外が投げられると期待してチェックをサボってはいけない(実際にx86に慣れたプログラマーがARMデバイスでよく踏む罠)。
Re:C言語なら (スコア:1)
なので、アセンブラレベルで0除算か検査して例外出すように変換しています
逆に、符号付整数加算はオーバフロー例外投げることがありますので、
通常は符号なし整数加算に変換されます
アセンブラでコーディングすることを「ほぼ」前提としないMIPSならではの仕様はこのほかにもあります
Re: (スコア:0)
> 逆に、符号付整数加算はオーバフロー例外投げることがありますので、
> 通常は符号なし整数加算に変換されます
符号付整数加算がオーバーフロー起こしたときの動作も未定義ですよ。だから別に変換しなくても(例外投げて死んでも)規格上は問題ないです。例外投げて死んでくれれば整数オーバーフロー系のセキュリティホールはだいぶ減らせると思うんですけどねえ。
Re: (スコア:0)
組み込みで例外を起こそうとしてゼロ除算をしたら、例外起きず結果が0になって困ったことがあった。
Re: (スコア:0)
組み込みだと*((int*)0)=0とかも大丈夫だったりするからなぁ…
# そもそも例外機構が存在するかどうかも怪しい世界
Re:C言語なら (スコア:1)
まあ0番地はブート用のROMだったりRAMだったりすることも多いので、0番地アクセスを禁止されると困るわけですが。
ちなみに、わたしが普段使っているコンパイラはゼロ除算は被除数がそのまま返ります。
つまり1で割ったのと同じ結果ですね。
Re: (スコア:0)
> 組み込みだと*((int*)0)=0とかも大丈夫だったりするからなぁ…
ちなみにCortex-M向けのgccで上記のコードを書くと、実行時にHardFaultが起きるようにコンパイラが故意に未定義命令を吐いてくれたりします。
一方で、*((int*)p)=0;と書いてもpの値をチェックしてくれるわけではないので、0を渡すと通ってしまうんですけど。
組み込み de ゼロ除算 (スコア:0)
いいなあ、除算命令あるんだ。
# 8bitPICとか、普通に乗除算命令とかないですよ。
# Cで使うと関数を作ってくれます。
## この手のMCUを使うと、C言語の標準に強烈な不満を感じます。
## 8bit演算しかもってないのにinteger promotionとかアホかと。
## まあ、intを8bitにするって手はあるけどsizeof(short)>sizeof(int)って不都合起きそう。
Re: (スコア:0)
Re: (スコア:0)
8ビットCPUのCで割り込み処理かいて単なる演算なのに関数よばれたりするけどその関数が再入可能でないので、
動作が不安定なったり暴走したり、それに気が付かず延々とデバグしてた人いたな
Re: (スコア:0)
未定義なら定義する方法が提供されていれば解決するのかな。
Re: (スコア:0)
仕様上未定義ということは、コンパイラを実装する人が
決めていいってことですよ。
仕様上で定義するには、C規格を改訂すればいいのです。
Re: (スコア:0)
C言語の思想的に、そういう最適化の足かせになるような改訂を受理することはまずないと思うけどね。ゼロ除算が仕様上未定義だから、コンパイラは除数がゼロになることは絶対にないと決めつけて最適化を行うことができる。同様に配列の範囲外へアクセスしたときの結果が未定義だから、境界チェックを省略できる。
Re: (スコア:0)
C99とか見てると、未定義動作はなるべく減らしたいなぁという意志が感じられなくもないですけどね。
Re: (スコア:0)
> 実際にx86に慣れたプログラマーがARMデバイスでよく踏む罠
ノシ
踏みましたよ。例外発生が常識だと思ってました…
Re: (スコア:0)
戻り値が未定義なだけで、例外が発生するとか定義されているのでは?
もちろん、爆発はしない。
Re: (スコア:0)