CS+ ループ内宣言のローカル変数のデバック

こんにちわ。ojojと申します。

ループ内で宣言したローカル変数をウォッチウィンドウからチェックすると値などが'?'と表示され困っております。
ループ外で宣言した場合は表示されるので、そうすればよいのですが
出来ればスコープを短くしたいです。

対処法をご存じの方いらっしゃいましたらご教授いただけないでしょうか。


環境
マイコン:RX23t
仕様ソフトウェア:CS+ ver8.06.00
コンパイラ:CC-RX V3.03.00
エミュレータ:RENESAS E1エミュレータ


状況(ソースを出せないのでイメージです。スミマセン。)

パターン1
main{
 while(1){
   static uint16_t test=0;
   test = 1;
  }//test がウォッチウィンドウで表示できない
}


パターン2
main{
 static uint16_t test=0;
 while(1){
  test = 1;
 }//test がウォッチウィンドウで表示できる。
}

以上です

Parents Reply Children
  • ほや様

    ご回答ありがとうございます。

    今回は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宣言は、あまり使うものではないので
    デバッガで見えるようにするために使うものではないですが、似たようなグローバル変数をいくつも増やしたくはないので個人的には好んで使っています。
    値が残っている事でかえってバグになってしまった経験もあるので、考えて使わないといけませんね。