Ein sehr sehr sehr komischer Fehler



  • Moin zusammen,
    ich habe einen wirklcih interessanten Fehler geschaffen, der mir echt Kopfzerbrechen bereietet. Ich habe eine Klasse mit einer Datenstruktur die ein Array enthält. Wenn ich jetzt mit einer Getfunktion die größe des Arrays abfrgaen will, was ein int-member der Klasse ist, werden die ersten beiden stellen des Arrays gelöscht. Warum habe ich keine Ahnung. Bei der Auskommentierten Version pasiert das gleiche übrigens. Einer von euch vielleicht? Hier ist der codekontext (die Datenstruktur, die das array enthält heißt bs):

    //aufruf der Funktion in einer anderen klasse
    for (int i=0; i<bs.getSize(); i++) {
    bs.print();
    int arrSize = bs[i].getDomainSize();
    //arrSize = bs[i].domainSize;
    cout << i<<" Veränderung? "<< " \n";
    bs.print();
    [...]
    }

    //die getFunktion
    int TView ::getDomainSize() {
    return domainSize;
    }

    //ein Teil der komischen Ausgabe:
    TestViewArray contains:
    position 0: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 1: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 2: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 3: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 4: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 5: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]

    0 Veränderung?
    TestViewArray contains:
    position 0: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [1628722220, 1628722220, 2, 3]
    position 1: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 2: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 3: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 4: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]
    position 5: TestView (domainsize: 4 , constantSize: 4, max: 3 , min: 0)
    contains: [0, 1, 2, 3]

    Tja und so geht das weiter, jeder Schleifendurchlauf werden die ersten 2 positionen des nächsten Arrays gefressen. .. ??? ...

    EvilEpsilon


  • Mod

    die klassendefinition solltest du uns nicht vorenthalten. bitte geeignete code-tags benutzen.



  • poste mal den ganzen Code

    EDIT: loool, mal wieder 2 Posts zur selben Zeit 😃



  • //Tview: 
    class TView {
    	public:
    		int* domain;
    		int max;
    		int min;
    		int domainSize; //can shrink if one value is dropped
    		int conSize; //constant
    		string name;
    public:
    	TView() {
                domain = NULL;
                max =0;
                min = 0;
                domainSize=0;
                conSize = 0;
                name  = " ";
        }
    
     void TView::init(int pDomainSize, int pRangeMin, int pRangeMax, string pName) {
        conSize = pDomainSize;
        domainSize = pDomainSize;
        //TODO conSize initialisiert??
        domain = new int[conSize];
        min = pRangeMin;
        max = pRangeMax;
        name = pName;
        if (max - min != conSize-1) {
           cout << "Error in TView() for range domain: range does not fit in array size, corrected\n";
           max = min + conSize - 1;
        }
        for (int i=0; i<conSize; i++)
            domain[i] = i+min;
      }
    
    	~TView() {
    		delete domain;
    	}
    
    	void TView ::print() {
    		cout << "TestView " << name << " (domainsize: "<< domainSize <<" , constantSize: " << conSize <<", max: " << max << " , min: " << min << ") \n   contains: [";
    		for (int i=0; i<conSize; i++) {
    			if (i< conSize -1) cout << domain[i] << ", ";
    			else cout << domain[i] ;
    		}
    		cout << "]\n";
    	}
    
      //returns index of value or -1 if it is not contained in domain
      int TView ::find(int val) {
           for (int i=0; i< conSize; i++)
               if (domain[i] == val) return i;
           return -1;
      }
    
      //returns domainArray without -1 values (empty positions)
      //if domain empty: return value = NULL
      int* TView ::getDomain() {
            if (domainSize == 0) {
               cout << "in Tview.getDomain: domain is empty!\n";
               return NULL;
            }
            int* ret =new int[domainSize];
            int countPos=0; //
            for (int i=0; i< conSize; i++) {
                if (domain[i]!= -1) {
                   ret[countPos] = domain[i];
                   countPos++;
                }
            }
            return ret;
      }
    
      int TView ::getDomainSize() {
          //cout <<"hier\n";
          //print();
          return domainSize;
      }
    
      int TView:: getMin() {
          return min;
      }
    
      int TView:: getMax() {
          return max;
      }
    
    };
    
    //---------------------------------------------------------------------
    class TViewArray {
          public:
    	TView* array;
    	int size;
    	string name;
    
       //constructor for range domain variable array
       //random = true: RangeMin and Max are random values in the given interval
       //or if RangeMax - RangeMin < 4
       TViewArray (int pSize, int pRangeMin, int pRangeMax, bool random, string pName) {
           cout << "ich war hier in TviewArray\n";
           size = pSize;
           name = pName;
           array = new TView[size];
           if (random == false || pRangeMax - pRangeMin < 4) {
              int dSize = 0;
              dSize = pRangeMax - pRangeMin +1;
              cout << "DSize " << dSize << " pRangeMax " <<pRangeMax << " pRangeMin " <<pRangeMin <<endl;
              for (int i=0; i< size; i++){
                  cout << "ich kam bis hier in TviewArray.. bla"<<i <<"\n";
                  //TView element (dSize, pRangeMin, pRangeMax, " ");
                  array[i].init(dSize, pRangeMin, pRangeMax, " ");
              }
              cout << "ich kam bis hier in TviewArray\n";
           }
    
           else {
              int min = 0, max = 0, dSize = 0;
              for (int i=0; i< size; i++){
                  min = rand() % pRangeMax + pRangeMin;
                  max = rand() % pRangeMax+ 2 + min ;
                  dSize = max - min +1;
                  //cout << "bla " << min << " " << max << " " << dSize << endl;
    
                  array[i].init(dSize, min, max, " ");
              }
           }
       }
    
    	 TView TViewArray ::operator[](int i) {
            //assert((i >= 0) && (i < size));
            return array[i];
         }
    
         ~TViewArray() {
            }     }
    
         void TViewArray ::print() {
              cout << "TestViewArray contains: " << endl;
              for (int i=0; i< size; i++) {
                  cout << "   position " << i << ": ";
                  //if (array[i] != NULL )
                  array[i].print();
                  //cout << "bla bla " << i << endl;
              }
              cout << endl;
         }
         int TViewArray ::getSize() {
             return size;
         }
    
    };
    
    //--------------------------------------------------------------
    class BppGrund {
        public: 
                 //changing values required for calculations 
                 //Sets: for every bin
                 SetVector possibleSet; 
                 SetVector requiredSet; 
                 SetVector candidateSet; 
                 bool* unpackedItems;
                 TViewArray l; 
                 TViewArray bs; 
    
                 //constant or given values
                 int loadLimit;
                 int totalSize; //sum of all itemSizes
                 int* itemSizes;
                 int amountOfItems;
         public: 
    
                 BppGrund(int n, int ll, int s[], int itemSum, int usedBins): 
                    possibleSet(usedBins, "possibleSet"),
                    requiredSet(usedBins, "requiredSet"),
                    candidateSet(usedBins, "candidateSet"),
    
                    l (usedBins, 0, itemSum, false, "l"),
    
                    bs (n, 0, usedBins, false, "b")
                    {
                     //Set constant parameters
                     cout << "hier anfang" << endl;
                     amountOfItems = n;
                     loadLimit = ll;
                     //TODO Fehler abfangen: parametercheck n>0 etc, Größe intArray == n
                     itemSizes = new int[n];
                     totalSize = itemSum;
    
                     amountOfUsedBins = totalSize / loadLimit;
    
                     unpackedItems = new bool[amountOfItems];
                     for (int i=0; i++; i<n)
                         unpackedItems[i] = false;
    
                     cout << "hier zwischen" << endl;
    
                     //TODO Sets initialisieren
                      cout << "hier ende" << endl;
                 }
    
                 ~BppGrund() {}       
    
                 void initSets() {
                     int arrSize = 0;
                     for (int i=0; i<bs.getSize(); i++) {
                         bs.print();
                         //TODO hier den komicshen FEhler rauswerfen. 
                         int arrSize = bs[i].getDomainSize();
                         //arrSize = bs[i].domainSize;
                         cout << i<<" Veränderung? "<< " \n";
                         bs.print();
                         int* arr = bs.getDomainAt(i);
                         if (arr == NULL || arrSize == 0) continue;
                         possibleSet.addManyToItemSets(arr, i,itemSizes[i], arrSize );
                         if (arrSize == 1) requiredSet.addManyToItemSets(arr, i,itemSizes[i], arrSize );
                         else candidateSet.addManyToItemSets(arr, i,itemSizes[i], arrSize );
                     } 
                 }
    };
    


  • omg?!

    ich habe jetzt beim durchschauen nichts gefunden. Probiers mal mit Debuggen. Die ersten beiden array müssen irgendwo neu erstellt worden sein.



  • EvilEpsilon schrieb:

    ...
    class TViewArray {
    ...
        TView TViewArray ::operator[](int i) {
            return array[i];
         }
    ...
    };
    ...
    

    Hi,

    obs was damit zu tun hat, weiß ich nicht, aber mich wundert ein wenig, dass der operator[]() per Wert zurückliefert ... das bedeutet, dass ein temporäres TView-Objekt erzeugt und zurückgeliefert wird.

    Verbunden damit, dass TView dynamisch Speicher erzeugt, aber keinen (selbstgeschriebenen) CpyCtor/operator=() bereitstellt, macht mich stutzig.

    üblicherweise deklariert man

    const T& operator[](size_t i);
    

    oder wenn der Client die Alemente ändern können soll:

    T& operator[](size_t i);
    

    und verhindert damit automatische Kopien.

    EDIT sagt noch, dass man nach einem new[] auch ein delete[] aufrufen sollte ....

    Gruß,

    Simon2.



  • Ja danke aber wie geht das?



  • Deine Pointer auf int, bool etc. sind ja sowieso nur Arrays. Da wäre es am einfachsten gleich vector zu verwenden. Dann kannst du dir nämlich deinen eigenen Kopierkonstruktor usw. sparen.
    Ansonsten lies einfach mal das hier
    http://tutorial.schornboeck.net/bigthree.htm



  • EvilEpsilon schrieb:

    Ja danke aber wie geht das?

    Was genau ?
    - operator[]() per Reference ? Einfach Returntyp anders deklarieren ("const TView&" bzw. "TView&" statt "TView"). Darfst natürlich nicht selbst eine Kopie zurückgeben (machst Du aber zeit auch nicht)
    - delete[] verwenden ? einfach statt "delete" "delete[]" schreiben.

    Allerdings ist Braunsteins Einwand schon gerechtfertigt: Wenn Du nicht selbst lernen willst, Container zu schreiben, solltest Du die STL-Container (am einfachsten std::vector) verwenden ... die nehmen Dir das alles ab.

    Wenn Du unbedingt selbst eine Array-Klasse schreiben willst, solltest Du noch etwas besser auf Deinen Speicherhaushalt achten. Mir ist z.B. nicht ganz klar, wem jetzt eigentlich eine "domain" gehört, die in getDomain() erzeugt wird ... wer löscht die denn wieder ? Ist es wirklich so, dass der Aufrufer eine eigene Kopie davon bekommen soll ?

    Mir scheint, dass Du die Dinge unnötig verkomplizierst ... schreib doch mal, was so ein View eigentlich ist und wer was mit einer Menge von Views anfangen soll.

    BTW: Ich habe nirgendwo die Deklaration oder Dfinition von "getDomainAt()" gefinden.

    Gruß,

    Simon2.



  • ja danke nochmal für die ideen. hab das intarray jetzt in eine map umgewandelt und damit läufts... ist auch nur ne testklasse das ding, also muß nur funktionieren. 🙂 *mir erlaub unschöne sachen zu programmieren*


Anmelden zum Antworten