0
gcc 4.7.2
c89

こんにちは、

チャネルの現在の状態に基づいて文字列を返す関数があります。使用するより良いテクニックは何だろうと思っています。最初に、メモリが常に有効になるようにメモリ プールを使用します。2 つ目は、return ステートメントで文字列を返すだけです。3 つ目は、スタックに割り当てられたローカル ポインターを使用して、それを返します。

いずれの場合も、文字列を出力するだけで、それ以外には使用しません。

どちらをお勧めしますか?

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

次のような関数を使用します。

MODULE_LOG(PRIO_DEBUG, "%s|%s",
        g_channel_state_to_string(channel->previous_state, channel->mem_pool),
        g_channel_state_to_string(channel->current_state, channel->mem_pool));

渡されたメモリ プールの使用

static char* g_channel_state_to_string(states_e state, apr_pool_t *mem_pool)
{
    char *channel_state = NULL;

    switch(state) {
    case CHANNEL_IDLE:
        channel_state = apr_pstrdup(mem_pool, "CHANNEL_IDLE");
        break;

    default:
        channel_state = apr_pstrdup(mem_pool, "CHANNEL_UNKNOWN_CHANNEL_STATE");
        break;
    }

    return channel_state;
}

return ステートメントで文字列を返す

static char* g_channel_state_to_string(states_e state)
{  
    switch(state) {
    case CHANNEL_IDLE:
        return "CHANNEL_IDLE";
        break;

    default:
        return "CHANNEL_UNKNOWN_CHANNEL_STATE";
        break;
    }
}

文字列リテラルをローカル ポインターに割り当てると、メモリがスタックに割り当てられ、関数が戻るときに存在しない可能性があるため、スタック ダンプが発生する可能性があります。

static char* g_channel_state_to_string(states_e state)
{
    char *channel_state = NULL;

    switch(state) {
    case CHANNEL_IDLE:
        channel_state = "CHANNEL_IDLE";
        break;

    default:
        channel_state = "CHANNEL_UNKNOWN_CHANNEL_STATE";
        break;
    }

    return channel_state;
}
4

1 に答える 1

4

return ステートメントで文字列を返すこと、文字列リテラルをローカル ポインターに割り当てることは、同じ解決策です。関数プロトタイプを return に変更しない限り、渡されたメモリ プールを使用するとエラーが発生しやすくなりますconst char*

3 番目のオプションでは、「CHANNEL_IDLE」リテラルのアドレスをポインター型のローカル変数に割り当てます。これはさらに値によって返されます。したがって、スタックに関係なく有効なプリミティブ アドレスが返されます (以下の説明を参照)。オプション 3 は、return 0xffffaaaa;

コード全体で定義された文字列リテラルは、リンカーによって慎重に清掃され、単一のコード セクションに再配置されます。プラットフォームによっては、ランタイム ローダーが実際に読み取り専用メモリに配置され、書き込みアクセスによってハードウェア アボートが生成される場合があります。オプション 1 では、コピーがヒープに置かれるため、返された文字列の変更が実行可能になります。あなたの使用例から、文字列の変更が必要だとは思えないので、「strdup」のオーバーヘッドは不要です。

オプション 2 と 3 は同一であるため、関数プロトタイプを変更して型を返すようconst char*にし、それらのいずれかを選択します。

PS 「わずかな効率性は忘れるべきです。97% の確率で言えば、時期尚早の最適化はすべての悪の根源です」D. Knuth

于 2013-02-22T08:39:07.820 に答える