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
  • ojojさん、こんにちは。NoMaYです。#以前は3ヶ月前でしたね。

    これは第一印象としては最適化を掛けたままでデバッグしているのだ思われます。もしそうであれば、最適化無しに設定変更してみて下さい。そうでなければ、その旨リプライして頂けますか?

  • NoMaY様、リプライありがとうございます。

    最適化はかけておりません。

  • ojojさん、こんにちは。NoMaYです。

    そうでしたか。こちらでもプログラムを書いて試してみます。

  • ojojさん、こんにちは。NoMaYです。

    こちらでプログラムを書いて試してみると、以下の画面コピーの通り、期待したように表示されましたね。(ただ、CC-RXとCS+のバージョンがそちらと少し違っているのは申し訳無いですけれども。CC-RX V3.04 CS+ V8.07)

    何か別の要因が関係していそうです。(もともとイメージ的なコードとのことですし。) この場合の通常の対処は、なぜ困っているこちらがそんなことをしないといけないのだ、という理不尽感はあるでしょうけれども、ソースを切り貼り&関数名/変数名を変更して、開示可能で再現可能なものを作成して頂くことになってしまうと思います。

    以下、CS+の画面コピーです。




    以下、ソースコードです。

    #include <stdint.h>
    #include <machine.h>
    void func1(void);
    void func2(void);

    void func1(void)
    {
        /**/while/**/(1){
            static uint16_t test=0;
            test = 1;
            test = 0;
            test = 1;
            nop();
        }//test がウォッチウィンドウで表示できない
    }

    void func2(void)
    {
        static uint16_t test=0;
        /*while(1)*/{
            /* static */ test = 1;
            test = 0;
            test = 1;
            nop();
        }//test がウォッチウィンドウで表示できる。
    }

    void main(void)
    {
        for(;;)
        {
            func1();
            func2();
        }
    }

     

Reply
  • ojojさん、こんにちは。NoMaYです。

    こちらでプログラムを書いて試してみると、以下の画面コピーの通り、期待したように表示されましたね。(ただ、CC-RXとCS+のバージョンがそちらと少し違っているのは申し訳無いですけれども。CC-RX V3.04 CS+ V8.07)

    何か別の要因が関係していそうです。(もともとイメージ的なコードとのことですし。) この場合の通常の対処は、なぜ困っているこちらがそんなことをしないといけないのだ、という理不尽感はあるでしょうけれども、ソースを切り貼り&関数名/変数名を変更して、開示可能で再現可能なものを作成して頂くことになってしまうと思います。

    以下、CS+の画面コピーです。




    以下、ソースコードです。

    #include <stdint.h>
    #include <machine.h>
    void func1(void);
    void func2(void);

    void func1(void)
    {
        /**/while/**/(1){
            static uint16_t test=0;
            test = 1;
            test = 0;
            test = 1;
            nop();
        }//test がウォッチウィンドウで表示できない
    }

    void func2(void)
    {
        static uint16_t test=0;
        /*while(1)*/{
            /* static */ test = 1;
            test = 0;
            test = 1;
            nop();
        }//test がウォッチウィンドウで表示できる。
    }

    void main(void)
    {
        for(;;)
        {
            func1();
            func2();
        }
    }

     

Children
  • NoMaY様

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

    ソースコードをコピーし、件のプロジェクトにソースコードを上書きしましたところ、私の環境でも正しく変数内容がウォッチウィンドウに表示されました。

    NoMaY様のおっしゃるとおり、私が原因と思っていた部分とは別の部分に原因があるようです。再現性のあるコード作れましたらまた投稿します。ありがとうございました。

  • ojojさん、こんにちは。NoMaYです。

    可能性の話としては以下のようなことも考えられますよ。

    ・ CS+のデバッグ情報解釈処理のバグ
    ・ CC-RXのデバッグ情報生成処理のバグ
    ・ CS+のウォッチ変数登録処理のバグ
    ・ ソースファイル名/パス名に記号(+-#など)や半角スペースが含まれていてCS+がうまく扱えないバグ
    ・ ソースファイル名/パス名に全角文字が含まれていてCS+がうまく扱えない(パス名だけならバグに分類かも)
    ・ そのソースに個別コンパイルオプションが設定されていて最適化が掛かったままだった
    [追記] パス名の件は、少なくとも以下のmain.cの話でも引っ掛かる筈なので今回は違うかな、と思い直しました。

    思うに調査の初期ステップとしては以下のような手順かと思うのです。(頂いた文面からは、そこまで試されたかどうか不明(main.cのようなソースで置き換えられただけかも)、でしたので、、、)

    くだんのウォッチ出来ない現象が発生している関数において関数の中身まるごと以下に置き換えて発生するのかどうか?

        while(1){
            static uint16_t test = 0;
            test = 1;
            test = 0;
            test = 1;
        }

     

     

  • NoMaYさん、

    手元のRL78環境では、 `static uint16_t test = 0; ` のコードをデバッガで確認したところ、testの変数そのものが、割り当て無しでした。(標準設定 volatile まで付けるとOK) 
    それでもデバッガ上では変数をモニタ対象に設定可能(?) という謎。

    追記.
    マウス操作を間違えて、`,`(カンマ)を変数として登録できました。当然ながら、値は ? でしたが。 (こちらも謎)

  • KatoNaganoさん、こんにちは。NoMaYです。

    > それでもデバッガ上では変数をモニタ対象に設定可能(?) という謎。

    ojojさんの方の案件で無くKatoNaganoさんの方の案件ですね。これは以下の挙動により一般的なことだと思います。

    (1) 現在ブレーク中のスコープでは見えなくても次に(或いはもっと先で)ブレークした時にスコープに入る変数を事前に登録することがある

    (2) 例えば、main()の先頭でブレークしている時(DOS/Windows/Linuxなどではデバッガ起動時の初期状態)にデバッグする予定の関数のローカル変数を事前登録する、など
    (3) 30年前とか40年前とか、コマンドライン操作が主流だったり、マウス操作がまだ洗練されていなかったり、だったころは(2)は普通のことだった(当時はDOS/UNIXなど)
    (4) そして、(1)の発想はユーザに拒絶反応を示されること無く現在に至っている

    (A) ただ、今思えば、当時はCPUパワーもメモリ容量も超貧弱だったので、全関数の全ローカル変数をスキャンすることが得策でなかった、という要因もあるかも
    (B) もし、数GHz/数十コア/数十Gバイトというのももよくある現在に初めてCソースコードデバッガが登場したとしたら、もっと厳しく変数存在確認チェックが行われたかも

    [追記]

    カンマは、カンマ式があるから、というのは詭弁強弁ですが、、、文法チェックが無いのはアカン、ですかね、、、

  • NoMaYさん、

    謎、、と書いた意味は、test という変数の実体が無いのに、追跡可能な変数として登録されるという意味です。
    CPUも(当然)コンパイラも違うので、RXでtestの変数(実体)が生成されるは分かりませんが。

    参考までに... (余計なお世話?)

  • > test という変数の実体が無いのに、追跡可能な変数として登録されるという意味です。
    ウオッチパネルは計算式でもキャストでも何でも書けなくてはいけないし、
    例えばサブプロジェクトのオブジェクトをロードすると変数が消えちゃうとかだと面倒くさくなるので
    入力に関しては中途半端に縛られるより何でもアリの方がユーザとしては有難いと思います。

    なぜ変数が表示されないのかが表示されれば親切だと思いますが、
    ブレークする度にエラーだか何だか分からないものが毎回表示されるのもうっとおしいので難しいですね。

  • KatoNaganoさん、こんにちは。NoMaYです。

    こんな感じのことかも。

    (1) 最適化により実体がなくなった変数は以下のように表示して欲しい

    The variable is optimized out.

    (2) 他方、最適化がどうのこうのに関係なく、スコープ内に変数が無ければ以下のように表示して欲しい

    The variable is not found in the current scope.

    (3) あと、変数名として明らかにおかしいとか、式として明らかにおかしとか、なら以下のように

    Invalid variable name
    Invalid expression

    (4) メモリ空間外(ROM/RAM/外部メモリマッピング領域外)とか、なら以下のように

    The address is invalid memory area

    ちなみに、(1)のような表記はe2 studio(rx-elf-gdb)で見掛けた覚えがあります。(CC-RXだったかGNURXだったかは記憶に定かではないですけれども、、、)

  • NoMaYさん、変数表記に関する件、コメントありがとうございます。

    ローカル変数が正しく表示されないのは困ったものですが、それがアセンブラまでみないとなぜかが更に困ったもので、それが、ojojさんの元々の質問だったでしょうか。
    結局、現状では、簡便な方法は無いということですね。

  • KatoNaganoさん、こんにちは。NoMaYです。

    > ojojさんの元々の質問だったでしょうか。

    いえ、ちがいます。ojojさんの件で私が困惑しているのは、最適化を無効にしてもウォッチ出来ない変数がある、ということです。(ojojさんの最初の投稿ではループ内スタティック変数であることが問題なのかと予測していたようですが、私が提示したソースではループ内スタティック変数でもウォッチ出来たということで、(今は時間が取れないけれども、) 開示可能で再現可能なものを作成出来るかどうか後日やってみます、ということでした。)


    > 結局、現状では、簡便な方法は無いということですね。

    あと、こちらは所謂、個人の感想、的な話になりますけれども、もうCC-RX/RL/RHで標準最適化が掛かったものはアセンブラウィンドウやレジスタウィンドウやメモリウィンドウを併用して、かつ、コンパイラの最適化技術にそれなりの知見のある人でなければデバッグが困難なことは将来も変わらないだろうなぁ、と思っていますよ。

    頑張れば多少は進展があるのかも知れないかも、とも思いますけれども、たぶんルネサスさんのコンパイラ開発チームさんも(どの開発チームでもそうでしょうけれども)やることは山積みでしょうし、完璧なまでのデバッグユーザエクスペリエンス(Appleさんとか好きそうな言葉ですけれども)は最適化を無効化しないと無理なものだと思っていて、それにも関わらず頑張ることの費用対効果は良くないだろうなぁ、とか思ったりしているのです。

    GCCの話になりますけれども、最適化とデバッグし易さの両立を目指した -Og という最適化レベルがあるのですが、それでもoptimized outされる変数があったりして、一度は  -Og を使う決心をしたものの結局 -O0 を使うことにしました、なんていう投稿がstackoverflowというサイトに投稿されていたりしました。(CMakeのissuesをなんとなく見ていたらリンクが書かれていたので覗いてみて知りました。)

    What's the difference between a compiler's `-O0` option and `-Og` option?
    stackoverflow.com/questions/63386189/whats-the-difference-between-a-compilers-o0-option-and-og-option/63386263#63386263

    Debug build should use -Og
    gitlab.kitware.com/cmake/cmake/-/issues/22969

    かくいう私も以下の投稿をしたことがありました。

    TB-RX65N/TB-RX231/TB-RX130+CC-RX/GNURXでCoreMark®ベンチマークを動かせるようにしてみようと思います
    japan.renesasrulz.com/cafe_rene/f/forum21/6022/tb-rx65n-tb-rx231-tb-rx130-cc-rx-gnurx-coremark/39589#39589
     「
    私は今まで、GNURXでデバッグ最適化(-Ogオプション)を指定すれば、充分なデバッグ性とそこそこの最適化が両立しているのだと思い込んでましたが、単に私の思い込みだったようです。


    デバッグ最適化 -Og では思い込んでいたほどには充分に変数内容が表示されるわけではなかった


    最適化無し -O0 であれば思い込んでいたような充分な変数内容が表示されるのであった


  • > デバッグ最適化 -Og では思い込んでいたほどには充分に変数内容が表示されるわけではなかった
    GCCのマニュアルを見ると、
    https://gcc.gnu.org/onlinedocs/gcc-10.3.0/gcc/Optimize-Options.html
    -Og は 「-O1 から」コードの順番に影響する最適化のいくつかを抜いたものなので、それなりに最適化が利いています。
    -fipaナントカの最適化が変数に影響していると思います。