Object wird ueberschrieben oder geloescht



  • Ich habe folgendes Problem: Ich habe eine Methode(iterate_qrpCubes), die eine andere Methode(calculateConflictingClause) aufruft. Dort wird einem globalen Object ein neuer Wert zugeordnet. Ist das Programm nun aber wieder in der übergeordneten Methode hat das Object (Object:: leftParentNode) wieder einen zufälligen anderen Wert. Kompiliert wurde mit g++.

    Hier die übergordnete Funktion. Hier werden bei beiden cout Anfragen die zufälligen anderen Werte angezeigt.

    void iterate_qrpCubes(int sizeOfTree) {
      for (int i = laststop; i <= sizeOfTree; i++) {
        if(index != 0) {
        std::cout << "anfang der forschleife beim Iterieren"<<  leftParentNode.clptr->cLiterals->meta.lit<< std::endl;
        }
      laststop = i;
      Reason conflicting = myQsolver.qrpCubes[i].conflicting;
      Literal reslit = myQsolver.qrpCubes[i].reslit;
      Reason antecedent = myQsolver.qrpCubes[i].antecedent;
      if(index != 0) {
        std::cout << "beim Iterieren"<<  leftParentNode.clptr->cLiterals->meta.lit<< std::endl;
      }
      calculateConflictingClause(conflicting, reslit, antecedent);
      index = 1; // it's not the first reason in a tree anymore
      }
    }
    

    Hier die untergeordnete Funktion:
    Wichtig sollten nur die letzten 8 Zeilen sein. Bei der cout Abfrage in der letzten Zeile stimmen die Werte noch.

    void calculateConflictingClause(Reason conflicting, Literal resLit, Reason antecedent) {
      std::vector <Literal> litContainer;
      size_t newBound = 0;
      if (index == 0) {
        leftParentNode = conflicting;
        LiteralPointerConf = conflicting.clptr->cLiterals;
      } else { // iterate the literals in the reasons
        std::vector <Literal> litContainer;
        Literal* LiteralPointerAnte = antecedent.clptr->cLiterals;
        //merge
        int countToBoundConf = 0;
        int countToBoundAnte = 0;
        Literal resLitInv = resLit.inv();
        while (((leftParentNode.clptr->cLiterals->meta.lit != 0) && (countToBoundConf < leftParentNode.clptr->cBound))
        && ((countToBoundAnte < antecedent.clptr->cBound) && (LiteralPointerAnte->meta.lit != 0))) {
          if ((leftParentNode.clptr->cLiterals->meta.lit == resLit.meta.lit) || (leftParentNode.clptr->cLiterals->meta.lit == resLitInv.meta.lit)) {
            leftParentNode.clptr->cLiterals++;
            countToBoundConf++;
            continue;  
          }
          if ((LiteralPointerAnte->meta.lit == resLit.meta.lit) || (LiteralPointerAnte->meta.lit == resLitInv.meta.lit)) {
            LiteralPointerAnte++; 
            countToBoundAnte++;
            continue;  
          }
          if (LiteralPointerAnte->meta.lvl < leftParentNode.clptr->cLiterals->meta.lvl) { // the lowest Level is right
            if ((LiteralPointerAnte->meta.lit != resLit.meta.lit) && (LiteralPointerAnte->meta.lit != resLitInv.meta.lit)) {
              litContainer.push_back(*LiteralPointerAnte);
              newBound++;
              LiteralPointerAnte++;
              countToBoundAnte++;
            } 
          } else {
              if ((leftParentNode.clptr->cLiterals->meta.lit != resLit.meta.lit) && (leftParentNode.clptr->cLiterals->meta.lit != resLitInv.meta.lit)) {
                litContainer.push_back(*leftParentNode.clptr->cLiterals);
                newBound++;
                leftParentNode.clptr->cLiterals++;
                countToBoundConf++;
              }
            }
          }
    
        while ((countToBoundConf < leftParentNode.clptr->cBound) && (leftParentNode.clptr->cLiterals->meta.lit != 0)) { 
          if ((leftParentNode.clptr->cLiterals->meta.lit == resLit.meta.lit) || (leftParentNode.clptr->cLiterals->meta.lit == resLitInv.meta.lit)) {
            leftParentNode.clptr->cLiterals++;
            countToBoundConf++;
            continue;  
           }
          if ((leftParentNode.clptr->cLiterals->meta.lit != resLit.meta.lit) && (leftParentNode.clptr->cLiterals->meta.lit != resLitInv.meta.lit)) {
            litContainer.push_back(*leftParentNode.clptr->cLiterals);
            newBound++;
          }
          leftParentNode.clptr->cLiterals++;
          countToBoundConf++;
        }
        while ((countToBoundAnte < antecedent.clptr->cBound) && (LiteralPointerAnte->meta.lit != 0)) {
          if ((LiteralPointerAnte->meta.lit == resLit.meta.lit) || (LiteralPointerAnte->meta.lit == resLitInv.meta.lit)) {
            LiteralPointerAnte++; 
            countToBoundAnte++;
            continue;  
          }
          if ((LiteralPointerAnte->meta.lit != resLit.meta.lit) && (LiteralPointerAnte->meta.lit != resLitInv.meta.lit)) {
            litContainer.push_back(*LiteralPointerAnte);
            newBound++;
          }
          LiteralPointerAnte++;
          countToBoundAnte++;
        }
    // Now Merge the Exist-Literals
    
        while ((leftParentNode.clptr->cLiterals->meta.lit != 0) && (LiteralPointerAnte->meta.lit != 0)) {
          if (LiteralPointerAnte->meta.lvl < leftParentNode.clptr->cLiterals->meta.lvl) { // the lowest Level is left
            if ((LiteralPointerAnte->meta.lit != resLit.meta.lit) && (LiteralPointerAnte->meta.lit != resLitInv.meta.lit)) {
              if (litContainer[newBound-1].meta.lvl > LiteralPointerAnte->meta.lvl) {
                litContainer.push_back(*LiteralPointerAnte);
              }
              if (litContainer[newBound-1].meta.lvl < LiteralPointerAnte->meta.lvl) {
                if (LiteralPointerAnte->isPos()) {
                  buildSkolemClause(litContainer, newBound);
                } else {
                  buildSkolemCube(litContainer, newBound);
                }
              }
            }   
            LiteralPointerAnte++;
          } else {
            if ((leftParentNode.clptr->cLiterals->meta.lit != resLit.meta.lit) && (leftParentNode.clptr->cLiterals->meta.lit != resLitInv.meta.lit)) {
              if (litContainer[newBound-1].meta.lvl > LiteralPointerAnte->meta.lvl) {
                litContainer.push_back(*leftParentNode.clptr->cLiterals);
              }
              if (litContainer[newBound-1].meta.lvl < LiteralPointerAnte->meta.lvl) {
                if (LiteralPointerAnte->isPos()) {
                  buildSkolemClause(litContainer, newBound);
                } else { 
                  buildSkolemCube(litContainer, newBound);
                } 
              }
            }
          leftParentNode.clptr->cLiterals++;
          }
        while (leftParentNode.clptr->cLiterals->meta.lit != 0) {
          if ((leftParentNode.clptr->cLiterals->meta.lit != resLit.meta.lit) && (leftParentNode.clptr->cLiterals->meta.lit != resLitInv.meta.lit)) {
            if ((litContainer[newBound-1].meta.lvl & ~forallMask) > (leftParentNode.clptr->cLiterals->meta.lvl& ~forallMask)) {
              litContainer.push_back(*leftParentNode.clptr->cLiterals);
            }
            if ((litContainer[newBound-1].meta.lvl & ~forallMask) < (leftParentNode.clptr->cLiterals->meta.lvl & ~forallMask)) {
              if (leftParentNode.clptr->cLiterals->isPos()) {
                buildSkolemClause(litContainer , newBound);
              } else {
                buildSkolemCube(litContainer , newBound);
              }
            }
          }
          leftParentNode.clptr->cLiterals++;
        }
        while (LiteralPointerAnte->meta.lit != 0) {
          if ((LiteralPointerAnte->meta.lit != resLit.meta.lit) && (LiteralPointerAnte->meta.lit != resLitInv.meta.lit)) {
            if(litContainer[newBound].meta.lvl > LiteralPointerAnte->meta.lvl) {
              litContainer.push_back(*LiteralPointerAnte);
            }
            if(litContainer[newBound].meta.lvl < LiteralPointerAnte->meta.lvl) {
              if(LiteralPointerAnte->isPos()) {
                buildSkolemClause(litContainer, newBound );
              } else {
                buildSkolemCube(litContainer, newBound);
              }
            }
          }
          LiteralPointerAnte++;
        } 
      }  
    
      litContainer.push_back(EndsignalLiteral);
      Literal* Pointerlits = &litContainer[0];
      std::cout<<Pointerlits->meta.lit;
      uint32_t notImportant = 111111;
      Clause* newParentNode = new Clause(Pointerlits, newBound, notImportant);
      Reason newLeftParentNode(newParentNode);
      leftParentNode = newLeftParentNode;
      std::cout << "Ende der Methode" << leftParentNode.clptr->cLiterals->meta.lit << std::endl;      
      }
    }
    

    Ich bin ratlos. zwischen diesen beiden Funktionen passiert nichts. Warum verändern sich die Werte. Ich nehme an dass ich irgendwie eine Speicherplatzverletzung begangen habe.


  • Mod

    Wie sieht denn Deklaration und Definition von leftParentNode aus?
    Ich nehme an, die gezeigten Funktionen sind Memberfunktionen, die in der Klassendefinition definiert werden?
    Hat es einen besonderen Grund, dass die if-Abfragen oft die Form
    if ( a || a )
    oder
    if ( a && a )
    zu haben scheinen?



  • camper schrieb:

    Hat es einen besonderen Grund, dass die if-Abfragen oft die Form
    if ( a || a )
    oder
    if ( a && a )
    zu haben scheinen?

    resLit vs. resLitInv


  • Mod

    hustbaer schrieb:

    camper schrieb:

    Hat es einen besonderen Grund, dass die if-Abfragen oft die Form
    if ( a || a )
    oder
    if ( a && a )
    zu haben scheinen?

    resLit vs. resLitInv

    Ah, doch nicht richtig hingeschaut. Wäre evtl. lesbarer, wenn man das umbrechen würde.



  • Clause* newParentNode = new Clause(Pointerlits, newBound, notImportant); 
      Reason newLeftParentNode(newParentNode); 
      leftParentNode = newLeftParentNode; 
      std::cout << "Ende der Methode" << leftParentNode.clptr->cLiterals->meta.lit << std::endl;
    

    Vielleicht:
    Die Zuweisung kopiert nur. newLeftParentNode löscht im Destruktor newParentNode. Am Ende der Funktion zeigt clptr auf Müll.



  • camper schrieb:

    Wie sieht denn Deklaration und Definition von leftParentNode aus?
    Ich nehme an, die gezeigten Funktionen sind Memberfunktionen, die in der Klassendefinition definiert werden?
    Hat es einen besonderen Grund, dass die if-Abfragen oft die Form
    if ( a || a )
    oder
    if ( a && a )
    zu haben scheinen?

    Danke, Camper für deine Antwort.
    Deklariert wird es in der Datei ganz oben über der Main und statisch. Dachte das es bei statischen Objekten keine Probleme bezüglich unerwarteten löschen gibt.

    Reason leftParentNode;
    Reason newLeftParentNode;
    

    Die Klasse Reason sieht folgendermaßen aus:

    union Reason {
    
      // Constructors
      Reason( Literal l ): varIdx( static_cast<unsigned long>(l.idx()<<1) | 0x1 ) {}
      Reason( Clause* clause ): clptr(clause) {}
      Reason( unsigned long varid ): fake( varid ) {}
      Reason( void ): clptr(nullptr) {}
    
      // Copy constructor.
      Reason (const Reason& r) { fake = r.fake; }
    
      // Destructor
      ~Reason( void ) {}
    
      Reason& operator=( const Reason& r) { fake = r.fake; return *this; }
      Reason& operator=( const unsigned long f) { fake = f; return *this; }
      bool operator==( const Reason& r) const { return fake == r.fake; };
      bool operator<( const Reason& r) const { return fake < r.fake; };
      bool operator!=( const Reason& r) const { return fake != r.fake; };
    
      bool isBinary( void ) const { return ((fake & 0x1) != 0 ); }
      bool isNary( void ) const { return ((fake & 0x1) == 0 ); }
    
      unsigned long varIdx; // shifted to the left by one position, and tailed by a "1", so that it's ensured odd
      Clause* clptr;//pp
      unsigned long fake; // unsigned long: it has the same size of a pointer
    };
    


  • manni66 schrieb:

    Clause* newParentNode = new Clause(Pointerlits, newBound, notImportant); 
      Reason newLeftParentNode(newParentNode); 
      leftParentNode = newLeftParentNode; 
      std::cout << "Ende der Methode" << leftParentNode.clptr->cLiterals->meta.lit << std::endl;
    

    Vielleicht:
    Die Zuweisung kopiert nur. newLeftParentNode löscht im Destruktor newParentNode. Am Ende der Funktion zeigt clptr auf Müll.

    Da das object statisch und global ist sollte das doch nicht möglich sein. Ich dachte das wäre kein Problem zu kopieren, weil Kopien ja nicht mitgelöscht werden, wenn das Orginalobject helöscht wird.



  • Aha, dein Reason ist also ein Union, der eigentlich nix im Destruktor tut. Das wirft aber andere Fragen auf:
    1. Warum überhaupt als union?
    2. Vor allem: zahl*2+1 um von pointer zu unterscheiden?! Ja, mag auf deiner Zielplattform gehen, aber wozu das ganze?
    3. Du hast ein new Clause. Wem gehört die, wer löscht die wieder? => Tipp: kein new/delete verwenden.

    Zur Frage:
    vor dem Ende der untergeordneten Funktion wird die dort deklarierte Variable std::vector <Literal> litContainer; gelöscht. D.h. alle Literals darin werden auch zerstört. Nun hast du aber mit Literal* Pointerlits = &litContainer[0]; über Clause* newParentNode = new Clause(Pointerlits, newBound, notImportant); einen Pointer darauf in der newParentNode und dann auch in der leftParentNode, wenn ich das richtig sehe. Das ist aber nach Ende der Funktion nicht mehr gültig.


  • Mod

    union Reason {
    
      // Constructors
      Reason( Literal l ): varIdx( static_cast<unsigned long>(l.idx()<<1) | 0x1 ) {}
      Reason( Clause* clause ): clptr(clause) {}
      Reason( unsigned long varid ): fake( varid ) {}
      Reason( void ): clptr(nullptr) {}
    
      // Copy constructor.
      Reason (const Reason& r) { fake = r.fake; }
    
      // Destructor
      ~Reason( void ) {}
    
      Reason& operator=( const Reason& r) { fake = r.fake; return *this; }
      Reason& operator=( const unsigned long f) { fake = f; return *this; }
      bool operator==( const Reason& r) const { return fake == r.fake; };
      bool operator<( const Reason& r) const { return fake < r.fake; };
      bool operator!=( const Reason& r) const { return fake != r.fake; };
    
      bool isBinary( void ) const { return ((fake & 0x1) != 0 ); }
      bool isNary( void ) const { return ((fake & 0x1) == 0 ); }
    
      unsigned long varIdx; // shifted to the left by one position, and tailed by a "1", so that it's ensured odd
      Clause* clptr;//pp
      unsigned long fake; // unsigned long: it has the same size of a pointer
    };
    

    Das schreit schon mal nach verbotenem Aliasing. z.B. Initialisierung mit Zeiger dann Kopieren per fake-Alias. Witzigerweise könnte es (evtl.) sogar gehen, wenn man Copyctor und copy-Zuweisung default belässt. Jedenfalls ist die Verwendung von union hier völlig unangebracht. Wieso nicht einfach intern immer nur fake verwenden und die anderen Typen per Funktion bereitstellen? Auch sollte ggf. über explicit nachgedacht werden.

    struct Reason {
    
      // Constructors
      Reason( Literal l ): fake( static_cast<unsigned long>(l.idx()<<1) | 0x1 ) {}
      Reason( Clause* clause ): fake( reinterpret_cast<unsigned long>(clause) ) {}
      Reason( unsigned long varid ): fake( varid ) {} 
      Reason( void ): fake( 0 ) {}
    
      bool operator==( const Reason& r) const { return fake == r.fake; };
      bool operator<( const Reason& r) const { return fake < r.fake; };
      bool operator!=( const Reason& r) const { return fake != r.fake; };
    
      bool isBinary( void ) const { return ((fake & 0x1) != 0 ); }
      bool isNary( void ) const { return ((fake & 0x1) == 0 ); }
    
      Clause* clptr() const { assert( isNary ); return reinterpret_cast<Clause*>( fake ); }
      unsigned long varIdx() const { assert( isBinary ); return fake >> 1; }
    
      unsigned long fake; // unsigned long: it has the same size of a pointer
    };
    


  • Danke für die Anmerkungen. Diese Klasse Reason ist nicht von mir. Das Programm das ich schreibe ist nur eine Hilfsfunktion für ein westentlich größeres Programm, dass ich selber nicht in allen Teilen durchdringe. Von daher kann ich leider nicht sagen, welche Intention dahintersteckt. Aber ich werde die Anmerkungen weiterreichen. Vielen Dank nochmals 😃



  • wob schrieb:

    Aha, dein Reason ist also ein Union, der eigentlich nix im Destruktor tut. Das wirft aber andere Fragen auf:
    1. Warum überhaupt als union?
    2. Vor allem: zahl*2+1 um von pointer zu unterscheiden?! Ja, mag auf deiner Zielplattform gehen, aber wozu das ganze?
    3. Du hast ein new Clause. Wem gehört die, wer löscht die wieder? => Tipp: kein new/delete verwenden.

    Zur Frage:
    vor dem Ende der untergeordneten Funktion wird die dort deklarierte Variable std::vector <Literal> litContainer; gelöscht. D.h. alle Literals darin werden auch zerstört. Nun hast du aber mit Literal* Pointerlits = &litContainer[0]; über Clause* newParentNode = new Clause(Pointerlits, newBound, notImportant); einen Pointer darauf in der newParentNode und dann auch in der leftParentNode, wenn ich das richtig sehe. Das ist aber nach Ende der Funktion nicht mehr gültig.

    Das heißt ich setze den Vector litContainer ein paar Ebenen höher oder gleich global und dann müsste es gehen? Sobald ich daheim bin probiere ich es gleich aus. Vielen Dank euch allen. Ihr seid echt super.



  • Der Tipp hat super geklappt. Musste die litContainer nur global setzten und es ging einwandfrei.



  • Ich noch ein Pointer Problem und wollte um Hilfe fragen.
    Ich habe die untenstehende Funktion für das gleiche Progamm geschrieben. Und dachte es sei klüger das Clause Object statisch zu machen, damit es nicht automatisch gelöscht wird. Seither funktioniert es nicht mehr: Es kompiliert zwar aber wenn ich es laufen lasse, bekomm ich folgenden Fehlermeldung

    *** Error in `./SkolemCalculatorMain': free(): invalid pointer: 0x0831982c ***
    buildSkolemCubebussssildSkolemCubeAbgebrochen (Speicherabzug geschrieben)
    

    durch auskommentieren konnte ich eindeutig die Clausel als Problem identifizieren. ist Clause auskommentiert oder dynamisch geht es. Als Lehre von gestern, habe ich alle Pointer außer dem Iterator global deklariert. Hat vielleicht jemand nen Tipp?

    void buildSkolemClause(std::vector <Literal> litContainer, size_t newBound) {
    
      std::cout << "buildSkolemClause";
      for (auto it = litContainer.begin(); it != litContainer.end(); it++) {
        Lit = *it;
        litContainerForSkolemClause.push_back(Lit);
      }
      Pointerlits = &litContainerForSkolemClause[0]; // create a Pointer to the vector.
      uint32_t id_144 = 11;
      Clause NewSkolemClause(Pointerlits, newBound, id_144);
     // SkolemFunctions.push_back(NewSkolemClause);
    }
    

Log in to reply