- PR -

配列が勝手に変わる・・・。

投稿者投稿内容
Mercredi
会議室デビュー日: 2003/07/20
投稿数: 3
投稿日時: 2003-07-20 09:37
初めまして。
最近javaを初めたんですが、原因不明のバグに悩んでいます。
staticなクラスのメンバ変数が、勝手に内容が変わってしまうんです。
具体的には、

public class TEST{
int a[] = new a[255];

public TEST(){
// 要素を全て0で初期化
for(int i=0; i<255; i++) a[i] = 0;
}

public int get(int n){
return a[n];
}
}

このようなクラスに対して、

static TEST test = new TEST();
int b = test.get(0);

このような操作をすると、何故か負の値が返ります。
デバッグしてみると、コンストラクタはちゃんと処理され配列は0で初期化されてるんですが、test.getの時点でa[]の内容は全てが負の値(-155とか)になってます。
全く原因が分からないんですが、どなたか分かる方いますでしょうか?
困り果ててます・・・。

環境はWinXP、メモリは512MB
JBuilder7.0 を使っています。
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2003-07-20 09:53
まず、
コード:
int a[] = new a[255];


が理解できません。
Mercredi
会議室デビュー日: 2003/07/20
投稿数: 3
投稿日時: 2003-07-20 09:57
あ、書き間違いました。
すいません;

int a[] = new int[255];

こうでした。
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2003-07-20 10:47
コード:

static TEST test = new TEST();
int b = test.get(0);


この2つの行の間に、他のコードが実行される余地はないでしょうか?
・この2行の間にもコードが記述されている。
・他のスレッドが実行されている。

なぜなら、
1.testは finalでありませんので、別の TESTのオブジェクトで、上書き
 することが可能です。
 (finalにしなさいと言ってるのではありませんよ。)
2.TESTの aはパッケージ内から参照可能ですから、他のクラスからも
 書き換えることができます。
 (こちらは、privateにしたほうがいいです。その前に原因解明を!)

そうしたつもりはないとは思いますが、念の為。
1.の確認方法は、コンストラクタ実行中の thisと、getしようとしたときの
 thisが同じ物かどうか、デバッガまたはprint文等で確認してください。
2.の確認方法も同様ですが、コンストラクタとgetのときの a[]が同一のもの
 か確認してください。

同一でなければ、オブジェクト自体を上書きしたことになりますし、そうで
なければ、a[]の個々の値を上書きしたことになります。

[ メッセージ編集済み 編集者: Kissinger 編集日時 2003-07-20 10:51 ]
Mercredi
会議室デビュー日: 2003/07/20
投稿数: 3
投稿日時: 2003-07-20 12:40
返信ありがとうございますm(__)m
おっしゃる通りマルチスレッドで、newからgetまでは連続ではないんです。
教えてもらったことを確認したんですが、同一のオブジェクトかどうかはデバッグウインドウの[クラス名@***]の後ろの数字***を見ればいいんですよね?どうやら同じみたいです。(両方とも377でした)
てことはa[]の要素全てが何らかの原因で書き換えられたってことでしょうか。
書き換えられる負の数値はいつも違うんですが、全部同じ値なんです。むしろ初期化されていないような感じです。
a[]に値を代入する場所はコンストラクタだけなのですが・・・。
TESTは複数のクラスで宣言してるんです。グローバルで使いたいのでstaticにしてるのですが、この場合でもオブジェクトは複数作られるのでしょうか。同一のオブジェクトとして共有したいのですが・・・。
一応a[]をprivateやstaticにしても結果は同じでした。
何がいけないんだろう・・・。

unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-07-20 13:27
unibon です。こんにちわ。

引用:

Mercrediさんの書き込み (2003-07-20 12:40) より:
教えてもらったことを確認したんですが、同一のオブジェクトかどうかはデバッグウインドウの[クラス名@***]の後ろの数字***を見ればいいんですよね?どうやら同じみたいです。(両方とも377でした)


これは、これで良いはずです。

デバッガの表示がおかしいだけというデバッガのバグや仕様、
あるいは失礼ながらデバッガの操作や表示の見方を間違えている、
という可能性もありますので、
デバッガを使わずに一時的に System.out.println などを追加して、
値を表示させてみてはどうでしょうか。

あと、スコープが違う複数の変数がたまたま同じ名前だと、
なんらかの理由で変数を取り違えている可能性もあるので、
問題となっている変数の変数名をユニークなものに一時的に変えてみてはどうでしょうか。

ちなみに、以下、余談に近くなりますが、
私が過去に気づいたデバッガのバグとしては、
変数がある時点以降プログラム内で使われないと、それを見切られてしまうためか、
null を代入していないにもかかわらず、
その変数が勝手に null になってしまうことはありました。
これってバグではなくそういう仕様なのかもしれませんが。
また、JBuilder でも Eclipse でも起きました。
しかし、逆に、それ以外のデバッガのバグ(変数にある値が勝手に入るなど)は
まだ遭遇したことはありません。
take-f
会議室デビュー日: 2003/07/20
投稿数: 1
投稿日時: 2003-07-20 15:09
take-fです。こんにちは。

引用:

書き換えられる負の数値はいつも違うんですが、全部同じ値なんです。むしろ初期化されていないような感じです。


intの配列はnewしたときに全ての要素が0で初期化されます。負の値が入っているということは何らかの代入処理が行なわれているはずです。

引用:

TESTは複数のクラスで宣言してるんです。グローバルで使いたいのでstaticにしてるのですが、


ちょっと本題から外れますが。。。
複数のクラスでTESTクラスのオブジェクトをstaticで宣言して使用しているということでしょうか?その場合、異なるクラスで宣言したTESTオブジェクトは別々のオブジェクトになります。staticなインスタンス変数というのはあくまで「あるクラスの複数のオブジェクトで共有される」だけですので。
未記入
大ベテラン
会議室デビュー日: 2003/06/28
投稿数: 219
投稿日時: 2003-07-20 15:39
こんにちは。

> デバッグしてみると、コンストラクタはちゃんと処理され配列は0で初期化されて
> るんですが、test.getの時点でa[]の内容は全てが負の値(-155とか)になってます

一応念のためお尋ねしますが、この現象が発生するのはJBuilder上でしょうか?
それとも、他の環境(たとえばモバイル機器とか)で発生するのでしょうか?
(文面からはJBuilder上と読めますが、以前実機に配備したところ変数が初期化されていなかった経験があったので・・・。)

[ メッセージ編集済み 編集者: Ken-Lab 編集日時 2003-07-20 15:40 ]

スキルアップ/キャリアアップ(JOB@IT)