На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Странные ошибки , Помогите, уже 3ий день мучаюсь
    Это будет база данных, компилятор Borland C 3.1
    Компилятор подвисает после выполнения программы, или пишет "allocation error, system halted", или выдает "system unstable"
    Borland C 5.01 выдает либо тоже самое, либо "acces violation at 0x40c772: write of adress 0x860050"
    Помогит плиз, очень надо.


    #include <iostream.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    #include <stdio.h>
    #include <io.h>

    typedef int bool;
    const TRUE=1;
    const FALSE=0;
    const L=50;
    typedef char str[L];
    typedef str* sp;

    class TString{
    public:
     TString();
     operator const sp();
     void operator = (const char*);
    private:
     str theString;
    };

    TString::TString(){
     int i;
     for(i=0;i<=L;i++){
       theString[i]=0;
     }
    }

    void TString::operator = (const char* inp){
     int i;
     for(i=0;i<=/*strlen(inp)-1*/L;i++){
       theString[i]=inp[i];
     }
    }

    inline TString::operator const sp (){
     return &theString;
    }

    class TField{
    public:
     TField();
     bool Visible;
     bool IsIndex;
     TString Caption;
     sp GetName();
     sp GetData();
     void SetName(char* n);
     void SetData(char* d);
    private:
     TString Name;
     TString Data;
    };

    TField::TField(){
    }

    void TField::SetName(char* n){
     Name=n;
    }
    sp TField::GetName(){
     return Name;
    }

    void TField::SetData(char* d){
     Data=d;
    }

    sp TField::GetData(){
     return Data;
    }

    class TRecord {
    public:
     TRecord();
     TRecord(int n,TString* names);
     ~TRecord();
     int FCount;
     TField *Fields;
    private:
    };

    TRecord::TRecord(){
     FCount=0;
    }

    TRecord::TRecord(int n,TString* names){
     FCount=n;
     Fields=(TField *)calloc(n,sizeof(TField));
     for(int i=0;i<=n;i++){
       Fields[i].SetName(*names[i]);
       Fields[i].SetData("");
     }
    }

    TRecord::~TRecord(){
     free(Fields);
    }


    class TDataSet:public TRecord{
    public:
     TDataSet():TRecord(){}
     TDataSet(int n,TString* names,char* FName);
     ~TDataSet();
     void SetFileName(char* FName);
     sp GetFileName();
     void SetIndexFieldNames(char* name);
     sp GetIndexFieldNames();
     void Create();
     int Open();
     void Close();
     int Append();
     int GetRecCount();
     int GetCurrentRecN();
     void SetCurrentRecN(int n);
     void NextRec();
     void PrevRec();
     void ApplyChanges();
     void Sort(char* FieldName);
     TString *IndexFieldNames;
     bool Opened;
    private:
     TString FileName;
     void ReadRec();
     void WriteRec();
     TString IndexFields;
     int RecCount;
     int CurrentRecN;
     FILE *DataFile;
    };

    TDataSet::TDataSet(int n,TString* names,char* FName):TRecord(n,names){
      IndexFieldNames=(TString *)calloc(n,sizeof(TString));
      FileName=FName;
      Opened=FALSE;
    }

    TDataSet::~TDataSet(){
     free(IndexFieldNames);
    }

    void TDataSet::SetFileName(char* FName){
     FileName=FName;
    }

    sp TDataSet::GetFileName(){
     return FileName;
    }

    void TDataSet::SetIndexFieldNames(char* name){
     char* pos;
     char* name2;
     IndexFields=name;
     int i=0;
     int len,ipos;
     do{
       name2="";
       len=strlen(name);
       pos=strchr(name,';');
       if(pos==NULL){ipos=strlen(name);}
       else{ipos=pos-name;}
       strncpy(name2,name,ipos);
       name2[ipos]=0;
       IndexFieldNames[i]=name2;
       if(pos!=NULL){strcpy(name,pos+1);}
       i++;
     } while(pos!=NULL);
    }

    sp TDataSet::GetIndexFieldNames(){
     return IndexFields;
    }

    void TDataSet::Create(){
     char *s;
     int k,len;
     DataFile=fopen(*FileName,"w+");
     for(int i=0;i<FCount;i++){
       s=*Fields[i].GetName();
       len=strlen(s);
       fwrite(s,len+1,1,DataFile);
       s=" ";
       for(k=0;k<L-len-1;k++){
         fwrite(s,1,1,DataFile);
       }
     }
     int f1=fclose(DataFile);
     if(f1!=0){cout<<"error";}
    }

    int TDataSet::Open(){
       DataFile=fopen(*FileName,"r+w+");
       char *s;
       for(int i=0;i<FCount;i++){
         fread(s,L,1,DataFile);
         if(strcmp(s,*Fields[i].GetName())!=0){
    cout<<"error "<<*Fields[i].GetName()<<endl;
    return 1;
         }
      }
     return 0;
    }

    void TDataSet::Close(){
     fclose(DataFile);
    }

    int TDataSet::GetRecCount(){
     fseek(DataFile,FCount*L,SEEK_SET);
     RecCount=0;
     while(!feof(DataFile)){
       ReadRec();
       RecCount++;
     }
     RecCount--;
     SetCurrentRecN(0);
     return RecCount;
    }

    int TDataSet::GetCurrentRecN(){
     return CurrentRecN;
    }

    void TDataSet::SetCurrentRecN(int n){
     if(n<=RecCount && RecCount>0){
       fseek(DataFile,FCount*L*(n+1),SEEK_SET);
       ReadRec();
       CurrentRecN=n;
     }
    }

    void TDataSet::ReadRec(){
     char *s;
     char c=' ';
     int k;
     for(int i=0;i<FCount;i++){
       fread(s,L,1,DataFile);
       if(feof(DataFile)){*s=0;}
       Fields[i].SetData(s);
     }
    }

    void TDataSet::WriteRec(){
     char *s;
     char *s2;
     int k;
     int len;
     for(int i=0;i<FCount;i++){
       s=*Fields[i].GetData();
       len=strlen(s);
       fwrite(s,len+1,1,DataFile);
       s2=" ";
       for(k=0;k<L-len-1;k++){
         fwrite(s2,1,1,DataFile);
       }
     }
    }

    int TDataSet::Append(){
       if((DataFile=fopen(*FileName,"a+"))!=NULL){
         SetCurrentRecN(RecCount);
         RecCount++;
         WriteRec();
         fclose(DataFile);
       }
       return 0;
    }

    int main(){
     clrscr();
     int i;
     TString n[3];
     n[0]="Field0";
     n[1]="Field1";
     n[2]="someField2";
     TDataSet DataSet1(3,n,"file.txt");
     for(i=0;i<=2;i++){
       cout<<*DataSet1.Fields[i].GetName()<<endl;
     }
     char *s1;
     s1=*DataSet1.GetFileName();
     printf(s1);
     //cout<<s1<<endl;
     s1=*DataSet1.GetFileName();
     //cout<<s1<<endl;
     DataSet1.Create();
     //DataSet1.Open();
       //cout<<DataSet1.GetRecCount()<<endl;
       //DataSet1.SetCurrentRecN(0);
       //cout<<*DataSet1.Fields[0].GetData()<<endl;
     //DataSet1.Close();
     DataSet1.Append();
     getch();
     DataSet1.Append();
     //getch();
     TString s;
     s="some string";
     cout<<*s<<endl;
     cout<<*s<<endl;
     getch();
     return 0;
    }
      iostream и stdio вместе использовать не рекомендуют... значит на то есть причины, на которые ты рано или поздно наткнешься smile.gif

      в программе прпробуй написать так:
      ...
      void TDataSet::ReadRec(){
      char *s;
      char c=' ';
      int k;
      for(int i=0;i<FCount;i++){
        fread(s,L,1,DataFile);
        if(feof(DataFile)){*s=0; cerr<<"debug assertion !feof(DataFile) failed!!!"<<endl; exit(0);}
        Fields[i].SetData(s);
      }
      }
      ...

      (В етой же функции и ошибка содержится smile.gif)
      Сообщение отредактировано: Visitor -
        Правильно. В функции указанной Visitorom, куда ты читаешь данные из файла?! ohmy.gif
        Указатель s у тебя неинициализирован и вместо буфера указывает на неизвестные просторы памяти. Вот как они зафигачутся в важное место - система и валится! wink.gif
          DrunkArd, что-то я не понял про указатель.
          В указатель s читается инф. из файла и вызывается метод TFileld::SetData
          В методе строке TString присваевается этот самый указатель, а оператор присвоения для TString у меня перегружен и имеет такой код:

          void TString::operator = (const char* inp){
          int i;
          for(i=0;i<=L;i++){
            theString[i]=inp[i];
          }
          }

          Не понимаю в чем ошибка, обьясни подробнее плиз. Что значит указатель не инициализирован?
            Гм... возьми какой-нибудь хороший учебник по Си...

            В указатель никогда и ничего не пишется. Указатель, как сущность имеет место быть только в паре с объектом на который он указывает. Указатель указывает на какую-то область данных в памяти (переменную, например). (Переменная, конечно, может иметь тип "указатель", и ее значение можно менять, но мы меняем значение переменной типа "указатель", а не сам указатель smile.gif).

            В данном случае, переменная s содержит неопределенный указатель (указывающий неизвестно на что), так как она не инициализирована, и вот в ето "неизвестно что" и читаются данные. Так получилось, что "неизвестно что" оказалось самым уязвимым местом операционной системы. Оно так часто получается. smile.gif
            Сообщение отредактировано: Visitor -
              Visitor, а в моем случае, что ты предлагаешь делать? Вместо указателя char* использовать мой класс TString?

              Просто странно, когда делаешь так:

              char *s;
              s="sometring";

              то система не ругается.
                Проще всего вместо char *s написать char s[1000];
                Дело в том, что при
                s = "asdfghjkl";
                в s как раз помещается указатель на лежащую хде-то в памяти строку "asdfghjkl"...
                а при обращении *s = 'a' символ а помещается туда, куда указывает указатель, хранящися в s. Разница даже наглядно видна -- наличие или отсутстве вот етого оператора *
                  Visitor, если ты имеешь ввиду:

                   char s[1000];
                   *s="sgljsdf";

                  то такое не работает.
                  а посимвольно заносить как в массив гимморно.
                  Или я че-то не понял smile.gif
                    void TDataSet::ReadRec(){
                    char *s;
                    char c=' ';
                    int k;
                    for(int i=0;i<FCount;i++){
                      fread(s,L,1,DataFile);
                      if(feof(DataFile)){*s=0;}
                      Fields[i].SetData(s);
                    }
                    }

                    Хде тут хоть одно место, где требуется s = "asdfghjkl"?
                      void TDataSet::ReadRec(){
                      char s[1000];
                      char c=' ';
                      int k;
                      for(int i=0;i<FCount;i++){
                       fread(*s,L,1,DataFile);
                       if(feof(DataFile)){*s=0;}
                       Fields[i].SetData(s);
                      }
                      }

                      Думаешь будет работать?
                        А куда оно денется...
                        Кстати, у тебя еще такие функции есть...

                        Где, например, вместо new TString[n] используется calloc....
                        Сообщение отредактировано: Visitor -
                          Огромное спасибо, я попробую.
                          З.Ы: а разве указатель char * и указатель на массив char s[1000] это одно и то же?
                          Не скажет ли ф-я fread, мол че ты мне не такой указатель пихаешь? huh.gif
                            В Си имя массива имеет тип * const (указатель, константный).

                            Но тебе практически весь код придется переписать, в любом случае... Тут какая-то жуткая смесь С и C++...
                              Цитата
                              Где, например, вместо new TString[n] используется calloc....

                              А разве так нельзя?
                                Если бы TString был struct, без всяких там методов -- то пжл. С классами так в общем случае поступать нельзя.
                                  По хорошему делай так:

                                  void TDataSet::ReadRec(){
                                  char *s;
                                  char c=' ';
                                  int k;

                                  s=(char*)malloc(FCount);
                                  fread(s,sizeof(char),FCount,DataFile);

                                  // Из буфера s переноси данные куда тебе надо.

                                  free(s);
                                  }
                                  Будет работать быстрее т.к. не надо в цикле читать файл по одному байту
                                  Сообщение отредактировано: DrUnkard -
                                    а лучше вообще от alloc и stdio избавиться. smile.gif

                                    На MSVC, например, ето практически сразу вылетит, на певом же созданном объекте smile.gif
                                      Visitor, т.е new вызывает конструктор, а calloc нет?
                                        Да. Там ного всего происходит, но и ето в том числе.
                                          Visitor, да мне именно в Bc3.1 надо smile.gif Это без вариантов.
                                            Цитата (Visitor @ 24.11.03, 18:58)
                                            а лучше вообще от alloc и stdio избавиться. smile.gif

                                            На MSVC, например, ето практически сразу вылетит, на певом же созданном объекте smile.gif

                                            А я не знаю Вашего С++ и MSVC tongue.gif
                                            biggrin.gif

                                            Я смотрю, что он использует СИ-шные ф-ии типа fread() и пишу ему ответ в том же духе.
                                              А в BC вылетит тогда, когда ты уже допишешь до того места, хде потом с ужасом обнаружишь, что надцать кб кода надо переписывать smile.gif
                                                s=(char*)malloc(FCount);
                                                FCount - кол-во полей в записи
                                                Наверное ты имел ввиду:
                                                s=(char *)malloc(L); //L=50 - длинна моей строки по дефолту
                                                  To Visitor
                                                  У меня не забалУешь! biggrin.gif
                                                  Я С++ (в смысле ООП) не использую, поэтому отслеживаю всё ручками. tongue.gif

                                                  To EnvOder
                                                  Может и так, я не разбирался в твоей проге.
                                                  Мой тебе совет:
                                                  Раз работаешь с БД - лучше поменьше файловых операций в теле цикла. Это существенно ускорит работу и не будет раздражать пользователя. Так что читай в буфер столько сколько возможно, а потом ужЕ ковыряйся циклами в памяти.
                                                  Сообщение отредактировано: DrUnkard -
                                                    Откуда я знаю, fread() сишная или с++сная? smile.gif В хелпе не написано rolleyes.gif
                                                      дык я ж говорю -- нада книжку хорошую... или две smile.gif
                                                        Drunkard, по поводу файловых операций я знаю. Только вот ВС3 под виндой сам жрет свою же кучу, и остается ее около 60 кб smile.gif Мы это пару недель назад, здесь, на форуме выяснили.
                                                        Так шо с буффером тут не шибко разгуляешься. dry.gif
                                                        Сообщение отредактировано: Env0der -
                                                          И правда ведь заработало laugh.gif
                                                          Сердечно благодарю, а то я думал, что пришел звиздец моему курсачу.
                                                          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                          0 пользователей:


                                                          Рейтинг@Mail.ru
                                                          [ Script execution time: 0,0520 ]   [ 15 queries used ]   [ Generated: 17.07.25, 23:14 GMT ]