2

マルチタスク(RTOS)環境で動作するように「スパゲッティコード」Cモジュールをリファクタリングしています。

現在、非常に長い関数と多くの不要なグローバル変数があります。

1つの関数にのみ存在するグローバル変数をローカル変数に置き換えようとすると、ジレンマに陥ります。すべてのグローバル変数は、ローカルの「静的」のように動作します。たとえば、関数を終了して再入力しても、その値を保持します。

マルチタスクの場合、「静的」ローカル変数はグローバルから最悪です。それらは機能を再入力しないようにします。

すべての論理フローをトレースせずに、関数が可変値の再エントランスを保持するリレーであるかどうかを調べる方法はありますか?

4

6 に答える 6

8

簡単な答え: いいえ、ローカル変数の宣言が静的かどうかによって関数の動作が異なるかどうかを自動的に判断する方法はありません。元のコードでグローバルを使用する各関数のロジックを調べるだけです。

ただし、グローバル変数を静的なローカル スコープ変数に置き換えることが関数が再入可能ではないことを意味する場合、それがグローバルの場合も再入可能ではありませんでした。したがって、グローバルを静的なローカルスコープ変数に変更しても、関数が最初よりも再入可能になるとは思いません。

グローバルが実際にそのスコープでのみ使用された場合 (グローバルを削除するときにコンパイラ/リンカーが確認する必要があります)、動作は同じに近いはずです。物事が初期化されるときに問題がある場合とない場合があります。標準が何を言っているのか思い出せません。静的な初期化が C++ で行われるのと同じ時間に C で行われる場合、実行が最初に宣言に到達するときに、同時実行セーフ関数を非同時実行セーフ関数に変換します。

関数が再入可能であるかどうかを判断するには、ロジックを調べる必要もあります。標準で特に明記されていない限り (私はチェックしていません)、関数が静的変数を宣言しているという理由だけで、関数は自動的に再入可能ではありません。ただし、グローバルまたは静的のいずれかを重要な方法で使用する場合は、再入不可であると想定できます。同期がない場合は、同時実行に対しても安全ではないと想定します。

最後に、頑張ってください。このコードは、あなたが望む場所から遠く離れているように聞こえます...

于 2008-09-25T16:57:34.203 に答える
1

グローバル変数が本当に 1 つの関数でのみ使用されている場合、それらがグローバルであるという事実により、それらを使用する関数が再入不可になるため、それらを静的ローカル変数にすることによって何も失うことはありません。変数のスコープを制限することで、少し得をします。

1 つの関数だけで使用されているすべてのグローバルにその変更を加えてから、各静的ローカル変数調べて、非静的 (自動) にできるかどうかを確認する必要があります。

ルールは次のとおりです。変数が設定される前に関数で使用されている場合は、静的のままにします。

自動ローカルにできる変数の例 (int nplus4;関数内に " " を配置します (ゼロに設定する必要はありません。使用前に設定されているため、設定前に実際に使用すると警告が表示されます) 、便利なチェック):

int nplus4 = 0;         // used only in add5
int add5 (int n) {
    nplus4 = n + 4;     // set
    return nplus4 + 1;  // use
}

nplus4var は使用前に設定されます。static int nextn = 0;次の例は、関数内に " " を入れて静的にしておく必要があります。

int nextn = 0;             // used only in getn
int getn (void) {
    int n = nextn++;       // use, then use, then set
    return n;
}

注意が必要な場合があります。" nextn++" は設定ではなく、" " と同等であるため、使用および設定nextn = nextn + 1です。

注意すべきもう 1 つの点: RTOS 環境では、スタック スペースがグローバル メモリよりも制限されている可能性があるため、" char buffer[10000]" などの大きなグローバルを関数に移動する場合は注意してください。

于 2008-09-26T06:33:19.140 に答える
1

変数が初期化される前に使用されている場合にコンパイラが警告する場合は、疑わしい変数をその宣言で値を割り当てずにローカルにします。

警告を発する変数は、他のコードを変更せずにローカルにすることはできません。

于 2008-09-25T17:01:51.587 に答える
1

グローバル変数を静的ローカル変数に変更すると、変更の範囲が縮小されるため、少しは役に立ちます。ただし、同時実行の問題は依然として問題のままであり、これらの静的変数へのアクセスをロックして回避する必要があります。

しかし、やりたいことは、変数の定義をローカルとして使用される最高のスコープにプッシュし、それを必要とするものに引数として渡すことです。これには明らかに多くの作業が必要になる可能性があります (カスケード効果があるため)。同様に必要な変数を「コンテキスト」オブジェクトにグループ化し、それらを渡すことができます。

設計パターンEncapsulate Contextを参照してください。

于 2008-09-25T17:14:30.497 に答える
0

あなたが「グローバル」変数と「ローカル」変数と呼んでいるものの例を教えてください

int global_c; // can be used by any other file with 'extern int global_c;'

static int static_c; // cannot be seen or used outside of this file.

int foo(...)
{
   int local_c; // cannot be seen or used outside of this function.
}

あなたが持っているものとあなたが変更したもののいくつかのコードサンプルを提供していただければ、私たちはより良い質問に答えることができます.

于 2008-09-25T16:57:17.527 に答える
0

私があなたの質問を正しく理解していれば、あなたの懸念は、グローバル変数が 1 つの関数呼び出しから次の関数呼び出しまで値を保持することです。明らかに、そうではない通常のローカル変数の使用に移行する場合。それらを変更しても安全かどうかを知りたい場合は、コードを読んで理解する以外に選択肢はないと思います。問題の変数の名前を全文検索するだけでも、有益な場合があります。

完全に安全ではない手っ取り早いソリューションが必要な場合は、それを変更して、何が壊れているかを確認できます。ソース管理でロールバックできるバージョンがあることを確認し、事前にいくつかの単体テストを設定することをお勧めします。

于 2008-09-25T17:05:41.563 に答える