Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Ошибка при работе с динамической памятью


Автор: Anark1 3.3.2010, 18:45
Здравствуйте,
такая подзадача - считать из файла данные построчно и записать в массив строк в динамическую память (число строк около 150 000), а затем преобразовать этот массив строк в массив структур.
Уже измучался, какие-то непонятные ошибки, вылетающие в разных местах. По всей вероятности, или память как-то криво выделяется, или я где-то её запортил.
Сам код:

Код

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#define SECTION_SIZE 5000 //Размер одной секции, при исчерпании которой происходит realloc с увеличением места на еще одну секцию
#define ID_SECTION_SIZE 3000 
#define STR_LIMIT 300

//структуры для внутреннего представления данных
typedef struct
{
    int year;
    int month;
    int day;
} date;


typedef struct 
{
    char fam[15];
    char name[15];
    char otch[15];
    char s;
    date * dat;
    char town[15];
    int group;
    int marks[50];
} student;

//функция построчного чтения данных из файла
int ReadStrings(char * path, char *** StringList, long * count)
{
    FILE * f;
    long i;
    char line[STR_LIMIT], *temp;
    if (!(f = fopen(path,"r"))) return 1;
    i = 0;
    temp = (char*)malloc(sizeof(char)*STR_LIMIT);    
    while(fgets(temp,STR_LIMIT,f))
    {    
        if (i == *count)
        {
                        //при исчерпании секции, происходит реаллок с увеличением места на одну секцию
            *StringList = (char **)realloc(*StringList,sizeof(char**)*(*count+SECTION_SIZE));
            *count+=SECTION_SIZE;
        }
        *(*StringList+i) = temp;
        temp = (char*)malloc(sizeof(char)*STR_LIMIT);
        i++;
    }
    *count = i;
    fclose(f);
}

//функция создания массива структур
void StringsToStructs(char ** StringList,student ** students, long count)
{
    student * stud;
    int i, k;
    long num;
    char _date[20];
    for (num=0;num<count;num++)
    {
        stud = (student *)malloc(sizeof(student));
        i = 0;
        sscanf(StringList[num]+i,"%s",stud->fam);        i+=strlen(stud->fam);
        sscanf(StringList[num]+i,"%s",stud->name);        i+=strlen(stud->name);
        sscanf(StringList[num]+i,"%s",stud->otch);        i+=strlen(stud->otch); 
        stud->s = StringList[num][i]; i+=2;
        sscanf(StringList[num]+i,"%s",_date);        i+=strlen(_date); //Ошибка вот тут
        stud->dat = GetDateFromStr(_date);
        sscanf(StringList[num]+i,"%s",stud->town);        i+=strlen(stud->town);
        free(StringList[num]);
        for (k=0;k<50;k++)
        {
            sscanf(StringList[num]+i,"%d",stud->marks[k]);        
            i++; 
        }

        students[num] = stud;
    }
    free(StringList);
}

int main (int argc, char ** argv)
{
char ** StringList;
long count = SECTION_SIZE, ids_count = ID_SECTION_SIZE;
char * path = "Students.DB";
student ** students;
id_bal ** ids;
av_date * av_age;
double time1, time2;

StringList = (char **)malloc(sizeof(char *) * SECTION_SIZE);
ReadStrings(path, &StringList, &count);
students = (student **)malloc(sizeof(student*)*count);
StringsToStructs(StringList, students, count);    
return 0;
}


функция GetDateFromStr(date *) тоже моя, но её смысла указывать наверное нет, она из строки выделяет 3 числа и записывает в нужную структуру.
Еще важно сказать, что когда я нажал "отладить при помощи MS VS", то ошибка, которую я там увидел - "Необработанное исключение, нарушение прав доступа в 0x000000". Это как минимум странно.
Также гарантируется, что 15 символов, выделяемых в структуре для фамилии, имени и прочего хватит на размещение там данных.
Компилятор tcc.
Заранее спасибо.

Автор: Albor 4.3.2010, 10:34
Указатели нужно проверять после выделения паммяти.

Автор: Anark1 4.3.2010, 15:40
Вчера вечером потерял остатки разума, а сегодня вновь их обрел. Проблема во free и возможно некорректном использовании  sscanf.

Автор: Albor 4.3.2010, 16:26
Anark1, ткните пальцем почему free проблемная? У вас память выделяется в цикле, если в какой-то момент указатель получит NULL, то проблема будет где угодно, где этот указатель используется

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)