Повторно используемое адресное пространство в C?

#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 в область, в которой оно используется.