2015-05-16 3 views
-2

Я эту структуру и функцию:Я не могу выделить память для этой структуры

typedef struct{ 

     char *maze_size; 
     char *trophy; 
     int time_max; 
     char *moves; 

}gameHistory; 

Функция принимает указатель gameHistory *gameHistoryReaded для резервирования памяти, но не работают.

void loadGameHistory(char fileName[], gameHistory *gameHistoryReaded, int *statusCode){ 
     /* Here send error */ 
     *gameHistoryReaded = (gameHistory*)malloc(LENGTH_GAME_HISTORY*sizeof(gameHistory)); 
     (*gameHistoryReaded).maze_size = (char *)malloc(MAX_STRING*sizeof(char)); 
     (*gameHistoryReaded).trophy = (char *)malloc(MAX_STRING*sizeof(char)); 
     (*gameHistoryReaded).moves = (char *)malloc(MAX_STRING*sizeof(char)); 

     FILE *file = fopen(fileName,"rb"); 
     char line[200]; 
     char *token1; 
     if (file == NULL){ 
      printf("\nError de lectura: archivo no encontrado\n"); 
      *statusCode = 0; //Si se presenta algun error en la lectura del archivsetea en 0 (error) 
      exit(1); 
     } 
     fgets(line,200,file); 
     token1 = strtok(line,":"); 
     strcpy((*gameHistoryReaded).maze_size, token1); 
     token1 = strtok(NULL,":"); 
     strcpy((*gameHistoryReaded).trophy, token1); 
     token1 = strtok(NULL,":"); 
     strcpy((*gameHistoryReaded).moves, token1); 
     token1 = strtok(NULL,":"); 
     (*gameHistoryReaded).time_max = atoi(token1); 

     fclose(file); 

} 

int main(){ 

     char routegameHistory[] = "game_history.txt"; 
     int statusCode = 1; 
     gameHistory gameHistory; 

     loadGameHistory(routegameHistory, &gameHistory, &statusCode); 

} 

Code :: Blocks показал мне это:

ошибка: несовместимые типы при назначении типа 'gameHistory' от типа '' struct gameHistory *

Но я думаю, что struct хорошо объявлены, другие point, Я выделяю память для int time_max?

+2

Хорошо, я попробовал ответить, но, прочитав ваши другие сообщения, я ** настоятельно рекомендую взять правильный курс программирования/C (например, прочитать хорошую книгу). Сначала вы должны получить основы. Это также поможет не урезать ни одного вопроса по каждому вопросу и не сможет получить ответ в точку. Без обид! – Olaf

ответ

0

gameHistoryReaded является указателем на gameHistory структура.

Эта линия:

*gameHistoryReaded = (gameHistory*)malloc(LENGTH_GAME_HISTORY*sizeof(gameHistory)); 

назначает значных вернулся из malloc() в любых gameHistoryReaded указывает.

Возможно, не то, что вы хотите.

Не разыгрывайте указатель с помощью *.

1

Вы разыгрываете указатель gameHistoryRead, который дает структуру. Чтобы назначить результат malloc самому указателю, просто не разыщите (опустите *).

Почему вы передаете этот указатель на функцию в любом случае? Он перезаписывается мгновенно. Если вы намерены вернуть структуру malloc'ed в вызывающий объект, вам понадобится указатель на указатель (**gameHistoryRead). В этом случае первая строка будет правильной, так как вы присваиваете самому указателю.

Только что заметили: вы все-таки создали структуру, так почему вы сделали это? Это не имеет никакого смысла (я полагаю, теперь вы хотели заполнить переданную структуру, но почему malloc тогда?).

Просто удалите структуру malloc() или посмотрите на код ниже.

Однако это плохой дизайн. Было бы лучше вернуть указатель на структуру malloc'ed, NULL на ошибку (см. Удар кода). Обратите внимание, что вызывающий объект должен проверить результат перед доступом к возвращенной структуре.

Кроме того, вы забыли освободить() блоки malloc'ed в случае ошибки. Не забудьте освободить() все выделенной памяти, а не только первой структуры.

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

Неверный размер структуры malloc. sizeof(...) уже дает правильный размер (если вы не хотите возвращать массив, но тогда еще больше не так).

В main(): Вы не можете использовать одно и то же имя для переменной, как и для типа (и вы даже не должны думать о простом изменении случая - это препятствует читаемости); см. main().

Sidenotes:

  • Не бросает void * как вы делаете для результата таНоса(). См. here для пояснения.
  • Перед использованием проверьте результат работы malloc. Он может быть NULL (без памяти). Выделение NULL-указателя приводит к неопределенному поведению (UB). Это означает, что все может случиться (оно может даже пройти незамеченным).
  • Не используйте (* p) .m для доступа к элементу структуры из указателя. Вместо этого используйте ->, который был специально разработан для этого.
  • Если другие поля (maze_size, ...) всегда имеют постоянный размер, почему бы просто не использовать массивы (с постоянным размером), избегая malloc для каждого? Это делает очистку намного проще.

Лучше было бы:

gameHistory *loadGameHistory(char fileName[]) 
{ 
    bool error = false; 
    gameHistory *hist = 
      malloc(sizeof(gameHistory)); 
    if (hist == NULL) return; // fail instantly 

    hist->maze_size = malloc(MAX_STRING); // sizeof(char) is 1 by standard) 
    error |= hist->maze_size == NULL; 

    // alloc further blocks 

    // here do what you want. set error = true on error and skip rest 

    // finally: 
    if (error) { 
     // out of memory: free all other blocks 
     free(hist->maze_size); // if NULL, free does nothing (standard) 

     // ... 

     free(hist); 
     return NULL; 
    } 

    return hist; 
} 
+0

Ваше предложение (в первом параграфе) не будет работать, потому что указатель является локальной переменной для функции; так что вызывающий не увидит выделенную память (это явно намерение) –

+0

@MattMcNabb: Да, я отредактировал свой ответ, увидев все больше и больше проблем. Тем не менее, я подозреваю, что во втором абзаце. Последнее, что я видел, это то, что он фактически передает структуру функции, поэтому совершенно непонятно, почему он все равно структурировал структуру. Я всегда получаю немного ностальгию, видя такой код. Хотя тогда я был бы счастлив иметь что-то вроде SO (или Интернета). – Olaf

2

gameHistory gameHistory; ошибка. Имя типа нельзя повторно использовать как имя переменной. Предположим, вы имели в виду:

gameHistory history; 

Это выделяет память уже. Вам не нужно выделять лишнюю память. Просто удалите попытку malloc линии от вашей функции, и все будет хорошо.

Однако дальше в вашей функции не было бы проблемой:

strcpy((*gameHistoryReaded).maze_size, token1); 

До сих пор вы не сделали maze_size точку в любом месте, так что вы не можете копировать символы в нем. Вы можете либо сделать maze_size быть массив символов (в этом случае он не будет требовать больше выделения), или вы могли бы выделить место и точку в этом пространстве:

gameHistoryReaded->maze_size = strdup(token1); 

strdup функция делает malloc и strcpy на одном дыхании ,

та же проблема возникает с trophy и moves; и, наконец, вы должны каждый раз проверять token1 != NULL.