2015-06-26 4 views
0

Указатель на мою глобальную переменную поворачивается к crud после освобождения локального ресурса, который я использую для установки значения в c.c char указатели памяти и глобальные переменные

это .c класс

char* resource_directory; 
void getResourcePath() 
{ 
    char *basePath = SDL_GetBasePath(); 
    char* resource_dir = (char*)malloc(37 * sizeof(char)); 

    for(int i = 0; i < 25; i++) 
    { 
    resource_dir[i] = basePath[i]; 
    } 
    strcat(resource_dir, "resources/"); 
    resource_dir[36] = '\0'; 

    *resource_directory = *resource_dir; 
    free(basePath); 
    // free(resource_dir); <--- If I free here the value goes to crud 
} 

(эта линия ниже должна сказать, значение в resresource_directorydir равно значению в resource_dir) правильно?

*resource_directory = *resource_dir; 

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

Даже делая заявление печати адресов показывает, что у них разные адреса.

SDL_Log("%d, %d", &resource_directory, &resource_dir); 

пример вывода : 245387384, 1361037488

я чувствую, что я делаю глупую ошибку здесь, но я не знаю, что это такое.

+0

Не отвергни 'таНос()' 's возвращаемое значение, и не используйте 'SizeOf (Char)', так как он всегда один, и не напечатайте адреса с помощью спецификатора ''% d '', используйте' '% p" '. –

+0

@this (кто удалил комментарий) в этом контексте, используя 'sizeof (* resource_dir)' лучше, так как он выживет с изменением типа, не обращая внимания. –

+0

Это вопрос C++ или C? Если вопрос - C++, ответы могут быть разными. – kfsone

ответ

1

Эта линия,

*resource_directory = *resource_dir; 

является присвоение первого значения resource_dir очков, на неинициализированный указатель resource_directory, это эквивалентно

resource_directory[0] = resource_dir[0]; 

, который явно не то, что вы хотите.

Вам нужно присвоить указатель

resource_directory = resource_dir; 

но вы не должны использовать глобальную переменную для этого, и специально

  1. Не malloc(), вы должны free() все, что вы malloc() и глобальные переменные затрудняют это.

  2. Не используйте malloc() для объектов фиксированного размера, вместо того, чтобы объявить его как массив с соответствующим размером, как этот

    char resource_directory[37]; 
    
  3. строк Копирование с strcpy() вместо того, чтобы писать цикл вашей собственной личности

    for(int i = 0; i < 25; i++) 
    { 
        resource_dir[i] = basePath[i]; 
    } 
    

    woule быть

    strcpy(resource_dir, basePath); 
    
  4. . Одна вещь, которую вы должны заметить при использовании глобальной переменной, как это, заключается в том, что если вы вызываете getResourcesPath() более одного раза, вы собираетесь утечки ресурсов, если вы должны использовать глобальные переменные для переноса значений, которые должны проживать до тех пор, пока вся программа работает, постарайтесь сделать их инициализацию статичной, и вы можете полностью избежать использования глобальных переменных для этого, потому что все, что вы объявляете и инициализировали в стеке кадра main(), будет использовать ту же жизнь, что и программа, поэтому вы можете передать ее как параметры для любой функции, которая требует их от main(), если у вас много таких переменных, создайте структуру для их хранения и передайте структуру через функции, требующие этих ресурсов, это очень распространенный метод.

+0

все. Я несколько секунд бил головой о стену, а потом понял, что никогда не инициализировал ресурс_каталога! –

+0

спасибо за более подробное наблюдение. Можете ли вы расширить использование глобальных переменных? У меня есть две функции, одна из которых называется getresourcepath(), которая устанавливает глобальную переменную для пути ресурса. Затем я могу сделать getresource («shaders/vertexshader»), который будет использовать глобальный путь ресурса + эту строку для доступа и получения требуемого ресурса в виде строки, чтобы я мог его загрузить. Что вы подразумеваете для установки статических переменных в основном? в настоящее время этот код находится в .c файле, заголовок включен в main? Я попытался переместить resouce_directory [37] в main.c, но я не вижу массив char. –

0

Эти утверждения

SDL_Log("%d, %d", &resource_directory, &resource_dir); 

выходы, как целые значения адресов глобальных переменных resource_directory и локальной переменной resource_dir. Конечно, их адреса разные.

Что касается этого заявления

*resource_directory = *resource_dir; 

тогда он хранит первый символ строки, на которую указывает resource_dir по адресу, который хранится в указателе resource_directory. Однако первоначально resource_directory был инициализирован нулем как объект со статической продолжительностью хранения. Таким образом, программа имеет неопределенное поведение.

Я думаю, что вы имеете в виду следующее

resource_directory = resource_dir; 

То есть вы хотите, что resource_directory будет указывать на строку, построенной в функции.

И нет никакого смысла использовать оператор

free(resource_dir); <--- If I free here the value goes to crud 

necause в этом случае заявление

resource_directory = resource_dir; 

также не имеет смысла.

Если resource_directory необходимо указать на встроенную строку функций, вы не должны ее уничтожать.

Учтите, что использование магических чисел 37 и 25 делает программу неясной и подверженной ошибкам.

0

Указатель - это переменная, которая содержит числовое значение, которое является адресом ячейки памяти. Например, указатель NULL представляет собой переменную, содержащую значение 0. Присвоение понятия «isa pointer» to является способом уведомления компилятора вашего предполагаемого использования, то есть вы не можете использовать синтаксис указателя на переменные без указателя. Но пока вы не используете синтаксис указателя, они более или менее ведут себя как обычные переменные.

int i = 0; 
int* p = &i; 

int j; 
int* q; 

j = i; // j has the same value as i 
q = p; // q has the same value as p 

В конце кода выше, p и q указывают на тот же адрес. Мы используем только синтаксис * когда мы хотим разыменованием указатель:

q = p; 
*q = *p; // copies the `int` pointed to by `p` to 
// the `int` memory location pointed to by `q`, 
// which is the same location. 

Обратите внимание, что можно гнездовых указатели:

int** pp = &p; 

p является int*, так &p является int**.

pp - числовое значение, это адрес ячейки памяти, содержащей int*. *pp означает fetch the value at the memory location contained in pp, который будет извлекать второе числовое значение - значение, которое находится в p, что само по себе является int* и, следовательно, вторым адресом. **pp доставит нам целое число, на которое p баллов.

Вашего задания

*resource_directory = *resource_dir; 

копирует указываемое-значения, а не адрес.

Так как вы отметили свой вопрос, как C++ я собираюсь сделать вывод, предлагая эту альтернативную реализацию:

std::string resource_dir; 
void getResourcePath() 
{ 
    char *basePath = SDL_GetBasePath(); 
    resource_dir = base_path; 
    resource_dir += "resources/"; 
    free(basePath); 
} 

Если вам необходимо значение с-строковое resource_dir впоследствии использовать resource_dir.c_str().

В качестве альтернативы, если вам требуется выполнение C:

char* resource_dir; 
void getResourcePath() 
{ 
    const char subPath[] = "resources/"; 
    size_t length; 
    char *basePath = SDL_GetBasePath(); 
    if (resource_dir) 
     free(resource_dir); 
    length = strlen(basePath) + sizeof(subPath); 
    resource_dir = (char*)malloc(length); 
    snprintf(resource_dir, length, "%s%s", basePath, subPath); 
    free(basePath); 
} 
Смежные вопросы