strcpy и strcat иногда вызывают проблемы

привет, у меня есть код, как показано ниже

char *str ;

        strcpy(str, "\t<");
        strcat(str, time);
        strcat(str, ">[");
        strcat(str, user);
        strcat(str, "]");
        strcat(str, "(");
        strcat(str, baseName);
        strcat(str, ") $ ");

        printf("\String is now: %s\n", str);

Этот код кажется работающим, но когда я использую функцию анализа XCode, он говорит: «Аргумент вызова функции является неинициализированным значением», а также иногда вызывает сбой моей программы ... когда я удаляю его, он работает нормально ... Что с этим не так? Спасибо


person kanoz    schedule 31.08.2011    source источник
comment
Вы выделили память для str?   -  person George Kastrinis    schedule 31.08.2011
comment
@kanoz: это важно, потому что вы не можете писать ни во что, кроме законно выделенной памяти.   -  person sharptooth    schedule 31.08.2011
comment
Для справки в будущем, str обычно называют висячим или диким указателем: en.wikipedia.org/wiki/Dangling_pointer   -  person Paul R    schedule 31.08.2011


Ответы (3)


strcpy и strcat используются для копирования и объединения строк в выделенный массив символов.

Поскольку str не инициализирован, вы записываете куда-то в память, и это плохо, потому что вы портите другие данные. Это может работать в тот момент, но рано или поздно ваша программа рухнет.

Вы должны выделить память при объявлении str:

char str[100];

Кроме того, strcat неэффективен, так как ему нужно искать конец строки, чтобы знать, где объединять символы. Использование sprintf было бы более эффективным:

sprintf(str, "\t<%s>[%s](%s) $ ", time, user, baseName);

Наконец, если вы не можете гарантировать, что сгенерированная строка будет соответствовать массиву, вам лучше использовать snsprintf.

person Zmaster    schedule 31.08.2011

Вы не выделяете память и оставляете str неинициализированным. Все последующие записи выполняются через неинициализированный указатель, указывающий «куда-то» — это поведение undefined.

Вы должны выделить (а позже и освободить) память, достаточно большую для хранения результирующей строки:

char *str = malloc( computeResultSizeSomehow() );
if( str == 0 ) {
   // malloc failed - handle as fatal error
}

//proceed with your code, then

free( str );
person sharptooth    schedule 31.08.2011
comment
что такое calculateResultSizeSomehow()? - person kanoz; 31.08.2011
comment
Попробуйте прочитать что-нибудь об указателях, прежде чем пытаться их использовать. boredzo.org/pointers - person George Kastrinis; 31.08.2011
comment
@kanoz: Вы должны оценить, сколько памяти вам нужно. Это называется псевдокод. - person sharptooth; 31.08.2011

Это намного проще и без ошибок из-за переполнения буфера:

#define BUFFERSIZE 512
char str[BUFFERSIZE];

snprintf(str, BUFFERSIZE, "\t<%s>[%s](%s) $ ", time, user, baseName);
person wormsparty    schedule 31.08.2011
comment
sprintf печатает в строке, а не на вашем мониторе. - person George Kastrinis; 31.08.2011
comment
@wormsparty Вы имеете в виду массив фиксированного размера? Или спринтф? Потому что первое только ограничивает вас. - person George Kastrinis; 31.08.2011
comment
Если вам это нужно где-то еще, например, вернув его из функции: return strdup(str), и освободите его позже. - person wormsparty; 31.08.2011
comment
sprintf печатает массив символов в вашем хранилище, а не на ваш экран stdout(1)->output - person Hello World; 27.02.2020