こんにちわ。ojojと申します。
ループ内で宣言したローカル変数をウォッチウィンドウからチェックすると値などが'?'と表示され困っております。ループ外で宣言した場合は表示されるので、そうすればよいのですが出来ればスコープを短くしたいです。
対処法をご存じの方いらっしゃいましたらご教授いただけないでしょうか。
環境マイコン:RX23t仕様ソフトウェア:CS+ ver8.06.00コンパイラ:CC-RX V3.03.00エミュレータ:RENESAS E1エミュレータ
状況(ソースを出せないのでイメージです。スミマセン。)
パターン1main{ while(1){ static uint16_t test=0; test = 1; }//test がウォッチウィンドウで表示できない}
パターン2main{ static uint16_t test=0; while(1){ test = 1; }//test がウォッチウィンドウで表示できる。}
以上です
スコープ(関数名#変数名)を指定すれば良いのでは。http://tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/latest/CS+.chm/DebugTool-RX.chm/Output/db_P_watch.html
内部変数でもstaticならアドレスが一意に決まるのでスコープを指定すれば常時見えるようになるはずです。(関数内に同じ名前の変数を複数作った場合の区別の仕方は分かりませんでしたが、別名のシンボルが作られるのでそれも可能だとは思います)
ほや様
ご回答ありがとうございます。
今回はmain関数内なので
main#test
と登録し試しましたがうまくいきませんでした。
> うまくいきませんでした。が、「アドレスも含めて ? だった」という意味なら最適化の結果変数としての実体がなくなったのだと思います。宣言はstaticでもループを抜けないと分かっていれば参照される機会がないので不要と判断されたのでは。
ほや様 ご回答ありがとうございます
アドレス含めて?となっています。最適化レベルを0にしているのですが、そのような事態が発生するのでしょうか?
asmリスティングや逆アセンブル表示を見れば分かると思います。(初心者フォーラムとしては不適切な答えかもしれませんがここは逃げちゃダメだと思います)リスティングファイル(*.lst)で見ると内部変数は__$test$1のようなシンボルで生成され、アドレスの定義もされます。変数が実装されなければそれらもリスティングに出力されなくなるので何が起きたかはある程度推測できます。変数が固定値に置き換えられるような処理は、最適化が無効でも起こります。値を確認する必要があって消されたくないなら変数宣言にvolatileを付けてください。
ほや様 ご回答ありがとうございます。
アセンブラリスティング出力を確認したところ、変数のアドレスが定義されているような記述は確認できました。
00000004 __$test$4://変数名だけ変更しています。00000004 04000000 .lword 00000004H
また、volatileをつけて変数を宣言してもウォッチウィンドウに、変数の値やアドレスが'?'で表示される問題は改善されませんでした。
> 変数のアドレスが定義されているような記述は確認できました。そうなるとメモリ参照ではなくレジスタ参照に置き換えられているという可能性が残ります。
> volatileをつけて変数を宣言してもウォッチウィンドウに、変数の値やアドレスが'?'で表示される問題は改善されませんでした。
ええー。volatileが付いていたら何が何でもメモリから読み出してメモリに書き戻す処理は実装されるはずですけどね。
リスティングのコードがどうなっているか確認してみてください。
> __$test$4$4ですと?同じ変数名でいくつも持たせているのですか。それだとスコープを指定しても1個しか表示対象にならないと思います。同名の変数だとウォッチパネルでアドレスを参照させる書き方にするやり方ぐらいしか思いつきません。
>そうなるとメモリ参照ではなくレジスタ参照に置き換えられているという可能性が残ります。
レジスタ参照になっているというのはどこから判断つくのでしょうか。調べたのですがさっぱりで…
>volatileが付いていたら何が何でもメモリから読み出してメモリに書き戻す処理は実装されるはずですけどね。>リスティングのコードがどうなっているか確認してみてください。
確認しましたが、volatileの有無では、ほぼリスティングのコードは変わっていないようです。
>同じ変数名でいくつも持たせているのですか。
いえ、同じ変数名はつけていません。
すみません、アセンブラ言語に習熟おらず、現状ざっくりしか調査できてません。時間見つけてもう少し調べてみます。
スコープを指定してだめならアドレスで参照するしかないと思います。変数のアドレスが0x404なら *(uint16_t *)0x404 みたいな感じで。> レジスタ参照になっているというのはどこから判断つくのでしょうか。変数を更新する時にメモリから一旦読み出して更新した後で書き戻しているのか、最初に1回だけ読み出して更新をレジスタ上で行っている(初期値だけ参照してメモリを使っていない)のかをコードから読み取ってください。> 00000004 04000000 .lword 00000004Hこれは、セクションの先頭から0x04に変数が初期値4で配置されている状態です。初期値が4ではない値として宣言されていても演算結果が常に定数になるのであれば定数に置き換えられたと考えられます。
脇から、失礼します。
> volatileが付いていたら
volatile は、最適化の対象外にする指示ではなかったでしょうか?
CS+を使ってますが、どうもローカル変数は当てにならない印象(最適化は初期設定 .. 最適化あり)static宣言は、あまり使うものではないので、、(固定で領域確保される、、再帰呼出し時に問題有り)困ったら、アセンブラ表示するか、外部のグローバル変数にコピーする対応でやっています。あまり賢くない感じです。特にレジスタ割当だと、複数の変数が同じレジスタに割り当てられるのですが、スコープの判断できてないようだし、、(間違った値を表示)
参考までに。
[追記]
volatile ですが、確かに指摘のように最適化の対象外というより、値が変動するとかの意味で、正確には最適化の対象外とはちょっと違っていたようです。失礼しました。(結果的には同じでも)
> volatile は、最適化の対象外にする指示ではなかったでしょうか?volatileは最適化そのものを禁止するキーワードでなく、変数へのread/writeアクセスを「省略しない」ようにするためのものなので、最適化を無効にした設定でもvolatileがあるかないかでコードは違ってきます。> 特にレジスタ割当だと、複数の変数が同じレジスタに割り当てられるのですが、スコープの判断できてないようだし、、(間違った値を表示)レジスタが使い回される時には変数がoptimize out にされて見えなくなったりする現象も同じ理由だと考えます。コンパイラがどういう区切りでスコープをデバッグ情報に反映するかの、キメの細かさに依存すると思います。ソースを見ている人間から見たら何をやってるんだと感じるかもしれませんが、デバッガとしてはデバッグ情報の通りに動いてるだけなんでしょうね。> static宣言は、あまり使うものではないのでデバッガで見えるようにするために使うものではないですが、似たようなグローバル変数をいくつも増やしたくはないので個人的には好んで使っています。値が残っている事でかえってバグになってしまった経験もあるので、考えて使わないといけませんね。