2013-02-22 2 views
0
gcc 4.7.2 
c89 

Здравствуйте,Возвращаясь строку в функции

У меня есть функция, которая будет возвращать строку на основе текущего состояния канала. Просто интересно, какая будет лучшая техника для использования. Во-первых, я использую пул памяти, чтобы память всегда была действительной. Второй, просто возвращающий строку в оператор return. И третий, используя локальный указатель, выделенный в стеке и возвращающий это.

Во всех случаях я просто печатаю строку и не буду использовать ее ни для чего другого.

Какой из них Вы бы порекомендовали?

Большое спасибо за любые предложения,

Использование функции вроде этого:

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; 
} 

Возврат строки в обратном заявлении

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; 
} 
+1

Если вы рассматриваете последнее, результатом должно быть 'const char *', особенно если вы планируете использовать строковые литералы. И ваши строковые литералы не находятся в стеке; они находятся в сегменте только для чтения.В вашем 'g_channel_state_to_string()' выше единственное пространство стека - это параметр 'state' и локальный указатель, который даже на худшей платформе составляет всего 16 байт (AS/400 имеет 128-битные указатели, egads). – WhozCraig

ответ

4

Возвращение строки в операторе возврата и Присвоить строковой литерал локальный указатель .. одинаковые решения. Использование пула памяти, переданного в, более подвержено ошибкам, если вы не измените прототип функции, чтобы вернуть const char*.

В третьем варианте вы назначаете адрес литерала «CHANNEL_IDLE» локальной переменной типа указателя, которая далее возвращается значением. Таким образом, возвращается примитивный адрес, который остается действительным независимо от стека (см. Объяснение ниже). Вариант 3 идентичен return 0xffffaaaa;

Строковые литералы, определенные на протяжении всего кода, будут тщательно удалены компоновщиком и перемещены в единую секцию кода. В зависимости от вашей платформы во время загрузки загрузчик может фактически разместить ее в постоянной памяти, а доступ на запись может привести к сбою аппаратного обеспечения. Вариант 1 делает измененную модификацию строки жизнеспособной, потому что она копируется в кучу. Из вашего примера использования я сомневаюсь, что вы хотите изменить строку, поэтому накладные расходы «strdup» бесполезны.

Поскольку варианты два и три идентичны, я бы изменил прототип функции, чтобы вернуть тип как const char* и пошел для любого из них.

P.S. «Мы должны забыть о небольшой эффективности, скажем, около 97% времени: преждевременная оптимизация - это корень всех злых». D. Knuth

+0

+1 Котировка цитаты Кнут только стоял на голосовании. – WhozCraig

Смежные вопросы