古いコンパイラのバグ
普段はVisualCを使いながら、たまにDOS用でTurboCを使ったりします。
ちょっとした実験には手ごろだし、10年も使い慣れているからです。
しばらくはWindows専門でDOSをやってなかったけど久しぶりに使ってみると不思議なことがおきました。
どうも計算がおかしい!?
よく調べるとクラスがあやしいです。
昔はC++を使ってなかったので気づかなかったのですがクラスを高度に使いこなすと古いコンパイラはボロが出ます。
環境は次の通り
OS:WindowsMe
コンパイラ:TurboC++1.01(1990年製)
リンカー:TurboLink3.0(1990年製)
アセンブラ:TurboAssembler1.0(1988年製)
アセンブラがC++に対応してないのでvirtualキーワードを使うとエラーが出てしまいます。
まあ、年号からして仕方ないけど。
コンパイラのC++のサポートレベルはクラス実装、オーバーライド、多重継承ぐらいです。
名前空間、例外処理、テンプレートはありません。
今回のエラーはクラスのインラインにありました。
それを簡単にまとめたのが次の通り。
#include<stdio.h>
class Test
{
public:
int a()
{
int d=1;
if(d==1){
if(d==1){
printf("正しい\n");
return 1;
}
}
printf("間違い\n");
return 0;
}
int b();
};
int Test::b()
{
int d=1;
if(d==1){
if(d==1){
printf("正しい\n");
return 1;
}
}
printf("間違い\n");
return 0;
}
int c()
{
int d=1;
if(d==1){
if(d==1){
printf("正しい\n");
return 1;
}
}
printf("間違い\n");
return 0;
}
void main()
{
Test x;
int result1=x.a();
printf("帰ってきた答え=%d\n",result1);
int result2=x.b();
printf("帰ってきた答え=%d\n",result2);
int result3=c();
printf("帰ってきた答え=%d\n",result3);
}
|
古い仕様ではクラス定義はメンバのs宣言だけにし、メンバ関数の本体を外に出すのが常識でした。
今の時代ではJavaやC#のソースを見る限り、クラス定義の範囲内に関数を書いています。
本来ならクラス定義内で書いた関数はインライン展開されるんだけど、インラインできないfor文を使うと警告がでます。
それどころか正しい結果が出ないのが大問題であるけど。
| C\>ctest 正しい 間違い ←これが表示するのはおかしい 帰ってきた答え=0 ←この数値が期待通りでない 正しい 帰ってきた答え=1 正しい 帰ってきた答え=1 |
対策としては関数の中身をクラス定義の外にすることでしのいでいます。
気づかなければ、またハードが壊れることになりそう。(汗)
なお、アメリカのボーランドのサイトで英語版のTurboC++がダウンロードできるけど、バージョンが同じなので
バグは変わっていません。