C - структура проблемы - написание - PullRequest
0 голосов
/ 14 мая 2010

Я делаю программу на C, и у меня проблемы с памятью, я думаю.

Итак, моя проблема: у меня есть 2 функции, которые возвращают структуру. Когда я запускаю только одну функцию за раз, у меня нет никаких проблем. Но когда я запускаю один за другим, я всегда получаю сообщение об ошибке при записи во вторую структуру.

Функция struct item* ReadFileBIN(char *name) - читает двоичный файл. struct tables* getMesasInfo(char* Filename) - читает текстовый файл.

Мой код такой:

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int numberOfTables=0;
int numberOfItems=0;

//struct tables* mesas;
//struct item* Menu;

typedef struct item{
    char nome[100];
    int id;
    float preco;
};
typedef struct tables{
    int id;
    int capacity;
    bool inUse;
};
struct tables* getMesasInfo(char* Filename){
    struct tables* mesas;
    char *c;
    int counter,numberOflines=0,temp=0;
    char *filename=Filename;
    FILE * G;
    G = fopen(filename,"r");
    if (G==NULL){
        printf("Cannot open file.\n");
    }
    else{
     while (!feof(G)){
     fscanf(G, "%s", &c);
     numberOflines++;
        }
    fclose(G);
    }  
    /* Memory allocate for input array */
    mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables*));
    counter=0;
    G=fopen(filename,"r");
    while (!feof(G)){
        mesas[counter].id=counter;
        fscanf(G, "%d", &mesas[counter].capacity);
        mesas[counter].inUse= false;
        counter++;
    }
fclose(G);
numberOfTables = counter;
return mesas;
}

struct item* ReadFileBIN(char *name)
{
        int total=0;
        int counter;
        FILE *ptr_myfile;
        struct item my_record;
        struct item* Menu;
        ptr_myfile=fopen(name,"r");
        if (!ptr_myfile)
        {
            printf("Unable to open file!");
        }

        while (!feof(ptr_myfile)){
            fread(&my_record,sizeof(struct item),1,ptr_myfile);
            total=total+1;
        }
        numberOfItems=total-1;
        Menu = (struct item *)calloc(numberOfItems , sizeof(struct item));
        fseek(ptr_myfile, sizeof(struct item), SEEK_END);
        rewind(ptr_myfile);
        for ( counter=1; counter < total ; counter++)
        {
            fread(&my_record,sizeof(struct item),1,ptr_myfile);
            Menu[counter] = my_record;
            printf("Nome: %s\n",Menu[counter].nome);
            printf("ID: %d\n",Menu[counter].id);
            printf("Preco: %f\n",Menu[counter].preco);
        }
        fclose(ptr_myfile);
        return Menu;
}

int _tmain(int argc, _TCHAR* argv[])
{
    struct item* tt = ReadFileBIN("menu.dat");
    struct tables* t = getMesasInfo("Capacity.txt");
    getchar();
}**

ошибка, которую я получаю:

"Необработанное исключение в 0x00411700 в test.exe: 0xC0000005: расположение записи нарушения доступа 0x00000000."

в «Меню [counter] = my_record;»

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 14 мая 2010

Вы, кажется, выделяете блок памяти неправильного размера в getMesasInfo(): sizeof(struct tables*) дает вам размер указателя , а не размер структуры, на которую он указывает:

mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables*));

Так что вы можете легко перезаписать нераспределенную память. Правильное распределение должно быть

mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables));

или аналогично тому, как вы выделяете другой массив в ReadFileBIN():

mesas = (struct tables *)calloc(numberOflines, sizeof(struct tables));

Более того, я не знаю, намеренно или нет, но в ReadFileBIN() вы выделяете (1) и читаете (2) на одну запись меньше, чем общее количество записей:

    numberOfItems=total-1;                                             // 1
    Menu = (struct item *)calloc(numberOfItems , sizeof(struct item)); // 1
    fseek(ptr_myfile, sizeof(struct item), SEEK_END);
    rewind(ptr_myfile);
    for ( counter=1; counter < total ; counter++)                      // 2
    ...

Поскольку счетчик цикла начинается с 1 (вместо 0, как обычно в C), вы эффективно выполняете цикл total-1 раз. То есть вы читаете в элементы от 1 до total-1 массива. Однако реальные элементы массива индексируются от 0 до total-2, поэтому самый первый элемент в массиве остается неинициализированным, и в конце вы допускаете ошибку переполнения буфера.

1 голос
/ 14 мая 2010

У вас проблема с этими строками:

    numberOfItems=total-1;
    Menu = (struct item *)calloc(numberOfItems , sizeof(struct item));
    fseek(ptr_myfile, sizeof(struct item), SEEK_END);
    rewind(ptr_myfile);
    for ( counter=1; counter < total ; counter++)

Во-первых, вы устанавливаете numberOfItems на одно меньше , чем общее. Это неверно Вам даже не нужно numberOfItems; так как total имеет количество строк в файле, следующая строка должна быть Menu = (struct item*) calloc(total, sizeof(struct item));

Во-вторых, вы пытаетесь использовать Menu в качестве одноосновного массива в цикле for. С-массивы начинаются с нуля. Вы должны использовать цикл for for (counter = 0; counter < total; counter++).

Наконец, как указал Питер, в первой функции вы размещаете объект неправильного размера. Вам нужно malloc numberOfLines*(sizeof(struct tables) (не sizeof(struct tables*).

1 голос
/ 14 мая 2010

Чтобы проиллюстрировать точку зрения Петра:

struct tables {
  int id;
  int capacity;
  int inUse; /* bool is not a C type */
};

int main()
{
  printf("sizeof: %d\n",sizeof(struct tables*));
  printf("sizeof: %d\n",sizeof(struct tables));

}

Будет выводить:

sizeof: 4
sizeof: 12
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...