#c #pointers #c-strings
#c #указатели #c-строки
Вопрос:
В части программы, над которой я работаю, я назначаю имя по-разному в разных обстоятельствах, но я хочу сохранить имя в любом случае, очевидно. Итак, я сделал что-то вроде этого:
char *name;
if(*condition one*){
char namebuilder[30] = "";
//fill char array here
name = namebuilder;
} else {
name = info->name; //a char* from a struct
}
char otherstring[30] = "______________________________"
Итак, в основном проблема, с которой я сталкиваюсь, заключается в том, что когда функция принимает имя else
маршрута, оно остается и работает просто отлично. Но когда он создает namebuilder и создает имя, по какой-то причине otherstring
оно заканчивается тем же адресом, что и имя, и имя перезаписывается «__________________________«. Я не понимаю, почему это происходит или как я могу это предотвратить.
P.S: Я протестировал это, напечатав адреса name и otherstring , и в них хранится один и тот же адрес, но только в том случае, если использовался namebuilder .
Дополнительная информация: это небольшая программа, которую я создаю, чтобы возиться с pthreads, так что, возможно, это может быть связано с потоковой обработкой, я думаю, но ни одна из упомянутых мной переменных не является глобальной.
РЕДАКТИРОВАТЬ: вот фактический код для тех, кто из вас спрашивает. struct thread_data { char *name; int max; };
void* race(void* params)
{
struct thread_data* info;
info = (struct thread_data*)params;
int len = strlen(info->name);
char* name;
if(info->max > len){
int i;
char newname[30] = "";
for(i = 0; i < info->max-1; i ){
if(i < len){
newname[i] = info->name[i];
} else {
char nextchar = randChar();
newname[i] = nextchar;
}
}
newname[info->max] = '';
name = newname;
} else {
name = info->name;
}
pthread_mutex_lock(amp;locker);
printf(name); //This correctly prints the name either way.
printf(" takes off!n");
pthread_mutex_unlock(amp;locker);
//begin trying to spell here.
int spelt = 0;
char spelling[30] = "______________________________";
// All code after this sees name as "______________________________" only if it came
// from the if statement and not the else.
Комментарии:
1. Гм, namebuilder перестает существовать при закрытии фигурной скобкой. Вы используете память после ее освобождения.
Ответ №1:
namebuilder
был сохранен в стеке, потому что он локальный внутри оператора if, после выхода из условия он был помечен как свободный, поэтому при объявлении otherstring
, которые имеют тот же тип и использование памяти, namebuilder
что и, он занял свое место в стеке.
Вот как вы можете это исправить:
char *name;
char namebuilder[30] = "";
if(*condition one*){
//fill char array here
name = namebuilder;
} else {
name = info->name; //a char* from a struct
}
char otherstring[30] = "______________________________";
Ответ №2:
Namebuilder является локальным для блока if. Вам нужно поднять его на одну область или выделить его в динамической памяти с помощью malloc() (не забудьте освободить () его, когда закончите!)
Комментарии:
1. Но я вывел name из области действия этого блока, и он работает нормально, но только после объявления otherstring он меняется.
2. @Jonathan: Такова тайна неопределенного поведения.
3. @Jonathan Как только namebuilder выходит из области видимости, компилятор может повторно использовать память, которую он занимал. В вашем случае он хранит там otherstring , но name по-прежнему указывает на него.
Ответ №3:
Ваш конструктор имен является локальным для блока if. Это означает, что, как только вы оставите это и попытаетесь использовать свой name
, доступ к name
точкам памяти в настоящее время является UB. Вам придется либо динамически выделять память для namebuilder — что означает, что вам нужно будет не забыть очистить ее позже — или вам придется перенести объявление namebuilder в область, в которой оно используется.