3

C89 gcc (GCC) 4.7.2

こんにちは、

私は誰かのソフトウェアを保守していて、静的構造のアドレスを返すこの関数を見つけました。static はそれがグローバルであることを示しているため、これは問題ないはずです。そのため、プログラムが終了するまで構造体のアドレスが使用可能になります。

DRIVER_API(driver_t*) driver_instance_get(void)
{
    static struct tag_driver driver = {
    /* Elements initialized here */
    };

    return &driver;
}

次のように使用します。

driver_t *driver = NULL;
driver = driver_instance_get();

ドライバー変数は、終了するまでプログラム全体で使用されます。

いくつかの質問:

  1. このようにすることは良い習慣ですか?
  2. ファイルレベルで関数の外で静的に宣言することに違いはありますか?
  3. メモリ プールを関数に渡し、メモリを構造体に割り当てて、構造体がヒープ上で宣言されるようにしてみませんか?

ご提案いただきありがとうございます。

4

2 に答える 2

3
  1. 一般的に、いいえ。関数を再入不可にします。コード作成者が何をしているかを本当に理解している場合は、制限付きで使用できます。

  2. 外部で宣言すると、構造体オブジェクトの名前でファイル レベルの名前空間が汚染されます。オブジェクトへの直接アクセスは他の場所では必要ないため、関数内で宣言する方が理にかなっています。他に違いはありません。

  3. ヒープに割り当てますか? パフォーマンスが低下します。メモリの断片化が発生します。また、呼び出し元は、メモリを明示的に解放するという負担を負います。回避できるときにユーザーに動的メモリの使用を強制することは、一般的には適切な方法ではありません。

    再入可能な実装のより良いアイデアは、外部から宛先構造体へのポインターを渡すことです。こうすることで、呼び出し元は、受信者のメモリを自由に割り当てることができます。


もちろん、ここに表示されているのは、シングルトンのようなイディオムの C 実装にすぎない可能性があります (関数の名前から判断すると、そうである可能性が最も高いです)。これは、関数が毎回同じポインターを返すことになっていることを意味します。つまり、すべての呼び出し元は、返されたポインターを介して同じ構造体オブジェクトを参照し、共有することになっています。そして、おそらく、同じオブジェクトを変更することを期待することさえできます (並行性がないことを前提としています)。その場合、ここに表示されるのは、グローバル変数の関数ラップされた実装です。したがって、その場合にここで何かを変更すると、実際には目的が無効になります。

于 2013-05-09T14:49:11.257 に答える