お世話になっております。
カイロスです。
RXまたはRLにおいて、CS+を用いたとき以下の2点に関して私の理解が正しいのかお聞きしたく質問しました。
・未初期化のグローバル変数は、起動処理後、0に初期化される。
・CS+の最適化レベルを「デバッグ優先」にしているため、volatile宣言は使用せずとも動作中のコード最適化による心配はしないで良い?
以上、よろしくお願いいたします。
どこのセクションに置かれている変数なのかと、どこから持って来たスタートアップコードかによります。CC-RXであれば_INITSCTが参照するテーブルに登録されたセクションがまとめてクリアされます。CC-RLであればcstart.asmみたいな名前のasmコード内でクリアする処理が有効になっていればそこで指定されているセクションがクリアされますが、コメントになっているかもしれません。GCCは_INITSCTがないのでasmソース内の0クリアする処理が.bss内を消しますが、コメントになっているかもしれません。本件はCS+だから関係ないですけど。いずれにせよセクション全体でクリアするかしないかの話になるので、個別の変数にvolatileが指定されているかには直接関係ありません。
ほやさん
ご回答ありがとうございます。
未初期化データに関しては、RXの_INITSCTとRLのcstart.asmを確認しクリアされるセクションを確認できました。
volatileに関しては、申し訳ありません私の質問の仕方が悪かったです。
・CS+の最低化レベルを「デバッグ優先」にしていれば、動作中のコードの最適化を気にしないで良いため、volatileは特に必要ない?
ということをお聞きしたかったです。
カイロスさん、こんにちは。NoMaYです。> CS+の最低化レベルを「デバッグ優先」にしていれば、動作中のコードの最適化を気にしないで良いため、volatileは特に必要ない?これは、デバッグ時にウォッチウィンドウで通常の変数の内容を見る場合のこと(しばしば最適化の影響で見ることが出来なくなることへのノウハウとしての対策で本来はvolatileが不要な変数についてもvolatileを付けることがあるけれどもそういった気遣いを不要に出来るかどうかということ)についてですか?それとも、最適化レベルを「デバッグ優先」に設定した状態で納品物件としてもビルドしてリリースする(業務の発注元へ納品する)予定なのでvolatileを付けなくても問題無いか(もちろんひととおり評価をして)といったことですか?私の考えとしては、前者はデバッグ時のことですので構わないし基本的にはvolatileを付けなくてもウォッチ出来る筈だと思いますし、後者も納品物件の最適化レベルを変更したことで発生したような不具合は不具合修正の為の追加費用無しでの対応を強要されるようなものでは無いように思います。ただ、前者に関してですが、先日、そのようにしていてもウォッチ出来ない変数がある、という相談がありました。(相談者さんは、その時には、今は時間が取れないけれども、 開示可能で再現可能なものを作成出来るかどうか後日やってみます、とのことでしたけれども、まだ結果は来ていないです。)CS+ ループ内宣言のローカル変数のデバックjapan.renesasrulz.com/cafe_rene/f/002-2095199602/8199/cs
NoMaYさん、ご返信ありがとうございます。
> それとも、最適化レベルを「デバッグ優先」に設定した状態で納品物件としてもビルドしてリリースする(業務の発注元へ納品する)予定なのでvolatileを付けなくても問題無いか(もちろんひととおり評価をして)といったことですか?
こちらに関してご質問させて頂いておりました。
最適化レベルが「デバッグ優先」ならばvolatileを付けなくても問題ないのかな?と思った次第です。現在、業務では基本的に最適化レベルを「デバッグ優先」にし、volatileを付けないものが多いのですが、過去ではvolatileを付けているものもあるため、どうしたものかな?と考えていました。
この辺りの状況を共有しておくべきでした!
私の理解としては、最適化レベルが「デバッグ優先」ならばvolatileを付けずとも問題はない(もちろん評価はする)。となっていますが、問題はないでしょうか?
カイロスさん、こんにちは。NoMaYです。言語規格として、最適化無し(もしくはデバッグ優先最適化)の場合には、こうなっていなければならない、という規定があるわけでは無いですので、自己責任にて、という色合いが濃くなりますけれども、評価をして問題が出ていないのであれば、私は構わないと思うのです。最適化無し(もしくはデバッグ優先最適化)の場合には、殆ど問題無いと思われる上に、且つ、評価をして問題が出ていなかったのだから、という発想です。ちなみに、ルネサスさんのRL78やRXのコード生成機能やスマートコンフィグレータが生成したコードでも、以下のスレッドの通りvolatileの位置を間違えたままになっていたり、RL78のAppliletのIARコンパイラ向け生成コードではvolatileが全く付いていなかったり(なぜ誰も文句を言わないのだろう)、とかもあったりしていますし、、、(最初に間違えると、後で直そうとしてもワーニング/エラーのconst hellと同様にvolatile hellみたいなことになってしまい、どうにも手が付けられない、という判断がされていても分からなくは無いのですけれども、、、)CS+のコード生成ツールが生成するポインタ変数でvolatile修飾子の記述位置がおかしいものがあるように思いますjapan.renesasrulz.com/cafe_rene/f/forum18/4052/cs-volatileRL78のApplilet(AP3だったかAP4だった咄嗟に思い出せません)のIARコンパイラ向け生成コードの例(私は余りに不安でしたので#if 0 ~ #endifで無効化して自前でCC-RLやGNURL78に合わせるようにしましたけれども、、、)(もっとも、それでも、volatileの記述位置がおかしいまま、ですけれども、、、)
/******************************************************************************* File Name : r_cg_serial_user.c* Version : CodeGenerator for RL78/G14 V2.05.05.01 [25 Nov 2020]* Device(s) : R5F104ML* Tool-Chain : IAR Systems iccrl78* Description : This file implements device driver for Serial module.* Creation Date: ******************************************************************************//******************************************************************************Includes******************************************************************************/#include "r_cg_macrodriver.h"#include "r_cg_serial.h"/* Start user code for include. Do not edit comment generated here */#include "r_cg_dtc.h"#include "UART3.h"#include "r_cg_userdefine.h"#if 0/* End user code. Do not edit comment generated here */#include "r_cg_userdefine.h"/******************************************************************************Global variables and functions******************************************************************************/extern uint8_t * gp_uart3_tx_address; /* uart3 send buffer address */extern uint16_t g_uart3_tx_count; /* uart3 send data number */extern uint8_t * gp_uart3_rx_address; /* uart3 receive buffer address */extern uint16_t g_uart3_rx_count; /* uart3 receive data number */extern uint16_t g_uart3_rx_length; /* uart3 receive data length *//* Start user code for global. Do not edit comment generated here */#endif /* #if 0 */extern volatile uint8_t * gp_uart3_tx_address; /* uart3 send buffer address */extern volatile uint16_t g_uart3_tx_count; /* uart3 send data number */extern volatile uint8_t * gp_uart3_rx_address; /* uart3 receive buffer address */extern volatile uint16_t g_uart3_rx_count; /* uart3 receive data number */extern volatile uint16_t g_uart3_rx_length; /* uart3 receive data length */
> volatileを付けなくても問題無いかvolatileを付ける必要のある場所には付ける、それ以外は付けない、でちゃんと分けて考えていれば問題ないと思います。volatile付けてないけど最適化無効にしてるから大丈夫とその時は思っても、ソースを他に流用したり、(未来の自分を含めて)事情を知らない人がうっかり最適化を有効にしたら発見の難しいバグになってしまう可能性があります。関数に入ってから出るまでに割り込み処理などで外部から書き換わる可能性のあるグローバル変数には最適化がどうでもvolatileは絶対に必要だし、タイミングを取るための空ループが最適化で消されないようにするためにvolatileを付けているなら、変数宣言をすぐ近くに書いておくか、この変数はvolatileが必要なんだとコメントを打ってうっかり消されないようにしておく必要があります。逆に大した理由がなくvolatileを書き散らしてしまうと、どれが本当に必要なのかが分からなくなるので非常に危険です。
いろいろと勉強になりました!
コード生成に関しては、他にも面倒になるパターンがあったりしたので、気を付けないといけないですね。
ほやさん、ご返信ありがとうございます。
確かに、最適化に関して今後変更になったときに現状のvolatileないでは問題が出てくる可能性がありますね。volatileに関して勉強不足であることを実感しましたので、そのあたりちゃんと勉強したいと思います!