AVL-Baum mit Iterator durchiterieren



  • DV: Lüke, ich bin dein Papa!
    L: Neeeeiiiinnnn!!!!!

    Ich habe auch schon daran gedacht, aber das reicht ja nicht aus für Direkt-Verknüpfungen. Wenn du dir Knoten 9 anschaust, der braucht eine Direkt-Verknüpfung mit der Wurzel. Die wäre der Ururgroßpapa.
    Also was machen?!

    http://www.fotos-hochladen.net/view/avlulpa3frw10.jpg



  • Man braucht keine Direktverbindung. Man kann sich über die Parent Zeiger ja bis zur Wurzel hocharbeiten. Der Algorithmus das nächste Elemente zu finden müsste so aussehen:

    Hat der aktuelle Knoten ein rechtes Kind?
     -> Ja: Gehe zu diesem und dann solange zum linken Kind bis es keins mehr gibt
     -> Nein: Gehe zum Elternknoten und widerhole dies solange bis man vom linken Kind in den Elternknoten kommt
    

    Hab ich mir gerade überlegt, könnten also noch Fehler drin sein.



  • sebi707 schrieb:

    Man braucht keine Direktverbindung. Man kann sich über die Parent Zeiger ja bis zur Wurzel hocharbeiten. Der Algorithmus das nächste Elemente zu finden müsste so aussehen:

    Hat der aktuelle Knoten ein rechtes Kind?
     -> Ja: Gehe zu diesem und dann solange zum linken Kind bis es keins mehr gibt
     -> Nein: Gehe zum Elternknoten und widerhole dies solange bis man vom linken Kind in den Elternknoten kommt
    

    Hab ich mir gerade überlegt, könnten also noch Fehler drin sein.

    Wenn du dir mal meine Zeichnung anschaust und dir vorstellst, dass der Startpunkt ein rechtes Kind mit dem Wert 1.5 hast, kommst du so in eine Endlosrekursion.

    Sei 1.5 rechtes Kind von 1, dann gilt:
    
    Hat 1 ein rechtes Kind? --> Ja, 1.5
    Gehe zu 1.5
    Hat 1.5 ein rechts Kind? --> Nein, gehe zu Elternknoten 1.
    Hat 1 ein rechtes Kind? Ja, 1.5.
    Gehe zu 1.5
    


  • Dann kommst du aber vom rechten Kind in den Elternknoten. Wenn das passiert gehst du zum Elternknoten vom Elternknoten usw. bis du wirklich von links in den Knoten kommst. Gibt es keine Elternknoten mehr, bist du also von rechts in die Wurzel gekommen hast du alle Konten besucht und bist fertig.



  • Bei Google findet man über "inorder successor binary tree" übrigens genau was ich mir überlegt hab. http://www.geeksforgeeks.org/inorder-successor-in-binary-search-tree/



  • Ah, jetzt verstehe ich dich! 🙂
    Vielen Dank! Werde ich mal ausprobieren! 🙂

    L. G.



  • Hallo,

    hat jemand eine Idee, weshalb ich bei Zeile 230 beim bool operator== immer null reingeliefert bekomme und die Membervariable ptr (Zeile 192) zu diesem Zeitpunkt ebenfalls null ist?! Ich bekomme deswegen am Ende, nach dem alle Elemente ausgegeben wurden, folgenden Fehler:

    double free or corruption (out): 0x00007ffe4d7f4100 ***

    #ifndef AVLTREE_H
    #define AVLTREE_H
    
    #include <memory>
    #include <algorithm>
    #include <assert.h>
    #include <iterator>
    #include <iostream>
    
    template <typename T>
    class AVLTree
    {
    private:
      class Node
      {
      public:
        int height = 0;
        T value;
    
        std::shared_ptr<Node> left = nullptr;
        std::shared_ptr<Node> right = nullptr;
        std::shared_ptr<Node> parent = nullptr;
    
        Node(T v)
          : value(v)
        {
        }
    
        // Kleiner-Ordnung
        bool operator<(const T& _value) const { return value < _value; }
      };
    
      std::shared_ptr<Node> root = nullptr;
    
      int getHeight(std::shared_ptr<Node> p)
      {
        if (p == nullptr)
          return -1;
        else
          return p->height;
      }
    
      int getBalance(std::shared_ptr<Node> p)
      {
        if (p == nullptr)
          return 0;
        else
          return getHeight(p->right) - getHeight(p->left);
      }
    
      std::shared_ptr<Node> insertR(T value, std::shared_ptr<Node> p)
      {
        if (p == nullptr) {
          p = std::make_shared<Node>(value);
        } else if (value < p->value)
        {
          std::shared_ptr<Node> temp = insertR(value, p->left);
          p->left = temp;
          temp->parent = p;
        }
        else if (value > p->value)
        {
            std::shared_ptr<Node> temp = insertR(value, p->right);
            p->right = temp;
            temp->parent = p;
        }
    
        p = balance(p);
    
        return p;
      }
    
      std::shared_ptr<Node> balance(std::shared_ptr<Node> p)
      {
        if (p == nullptr)
          return nullptr;
    
        p->height = std::max(getHeight(p->left), getHeight(p->right)) + 1;
    
        if (getBalance(p) == -2) {
          if (getBalance(p->left) <= 0)
            p = rotateRight(p);
          else
            p = rotateLeftRight(p);
        } else if (getBalance(p) == 2) {
          if (getBalance(p->right) >= 0)
            p = rotateLeft(p);
          else
            p = rotateRightLeft(p);
        }
    
        return p;
      }
    
      std::shared_ptr<Node> rotateRight(std::shared_ptr<Node> p)
      {
        assert(p->left != nullptr);
    
        std::shared_ptr<Node> q = p->left;
        p->left = q->right;
        q->right = p;
    
        p->height = std::max(getHeight(p->left), getHeight(p->right)) + 1;
        q->height = std::max(getHeight(q->left), getHeight(q->right)) + 1;
    
        q->parent = p->parent;
        q->right->parent = p;
        p->parent = q;
    
        return q;
      }
    
      std::shared_ptr<Node> rotateLeft(std::shared_ptr<Node> p)
      {
        assert(p->right != nullptr);
    
        std::shared_ptr<Node> q = p->right;
        p->right = q->left;
        q->left = p;
    
        p->height = std::max(getHeight(p->left), getHeight(p->right)) + 1;
        q->height = std::max(getHeight(q->left), getHeight(q->right)) + 1;
    
        q->parent = p->parent;
        q->left->parent = p;
        p->parent = q;
    
        return q;
      }
    
      std::shared_ptr<Node> rotateLeftRight(std::shared_ptr<Node> p)
      {
        assert(p->left != nullptr);
    
        p->left = rotateLeft(p->left);
        return rotateRight(p);
      }
    
      std::shared_ptr<Node> rotateRightLeft(std::shared_ptr<Node> p)
      {
        assert(p->right != nullptr);
    
        p->right = rotateRight(p->right);
        return rotateLeft(p);
      }
    
      bool contains(T value, std::shared_ptr<Node> p)
      {
        if (p == nullptr) {
          return false;
        } else {
          if (value < *p) {
            contains(value, p->left);
          } else {
            if (value > *p) {
              contains(value, p->right);
            } else {
              return true;
            }
          }
        }
      }
    
      std::shared_ptr<Node> findMax(std::shared_ptr<Node> p)
      {
        if (p == nullptr) {
          return p;
        } else {
          while (p->right != nullptr) {
            p = p->right;
          }
          return p;
        }
      }
    
      std::shared_ptr<Node> findMin(std::shared_ptr<Node> p)
      {
        if (p == nullptr) {
          return p;
        } else {
          while (p->left != nullptr) {
            p = p->left;
          }
          return p;
        }
      }
    
      struct iterator : std::iterator<std::forward_iterator_tag, T>
      {
        std::shared_ptr<AVLTree> tree;
        std::shared_ptr<Node> ptr;
    
        explicit iterator()
          : ptr(nullptr)
        {
        }
    
        explicit iterator(std::shared_ptr<AVLTree> tree, std::shared_ptr<Node> p)
          : tree(tree),
            ptr(p)
        {
          while (ptr->left != nullptr) {
            ptr = ptr->left;
          }
        }
    
        T& operator*()
        {
          return ptr->value;
        }
    
        iterator& operator++()
        {
          if (ptr != nullptr)
          {
            ptr = inOrderSuccessor(ptr);
          }
    
          return *this;
        }
    
        iterator operator++(int)
        {
          iterator tmp = *this;
          ++*this;
          return tmp;
        }
    
        bool operator==(const iterator& other) const { return ptr == other.ptr; }
        bool operator!=(const iterator& other) const { return ptr != other.ptr; }
    
      private:
        std::shared_ptr<Node> inOrderSuccessor(std::shared_ptr<Node> n)
        {
          // step 1 of the above algorithm
          if (n->right != nullptr)
            return tree->findMin(n->right);
    
          // step 2 of the above algorithm
          std::shared_ptr<Node> p = n->parent;
          while (p != nullptr && n == p->right) {
            n = p;
            p = p->parent;
          }
          return p;
        }
      };
    
    public:
      iterator begin()
      {
          std::shared_ptr<AVLTree> thisPtr(this);
          return iterator(thisPtr, root);
      }
      iterator end() { return iterator(); }
    
      void insert(T value)
      {
        if (root == nullptr) {
          root = std::make_shared<Node>(value);
        } else {
          insertR(value, root);
        }
      }
    
      bool contains(T value) { return contains(value, root); }
    
      T findMax() { findMax(root)->value; }
    };
    
    #endif // AVLTREE_H
    
    #include "avltree.h"
    #include <iostream>
    
    int main()
    {
        AVLTree<int> tree;
        tree.insert(5);
        tree.insert(3);
        tree.insert(8);
        tree.insert(10);
        tree.insert(-15);
        tree.insert(100);
        tree.insert(-4);
        tree.insert(0);
        tree.insert(17);
        tree.insert(200);
        tree.insert(101);
        tree.insert(151);
        tree.insert(300);
    
        std::cout << "Test" << std::endl;
    
        for (int elem : tree) {
            std::cout << elem << ",";
        }
    
        return 0;
    }
    


  • Ich habe mir deinen Code nicht komplett angeschaut, aber dieses Stück ist mit Sicherheit ein Fehler:

    std::shared_ptr<AVLTree> thisPtr(this);
    

    Dein Tree ist doch gar nicht dynamisch reserivert, sondern liegt auf dem Stack. Und selbst wenn es dynamisch wäre könntest du nicht so einfach den Besitz einem shared_ptr übergeben. Wenn du unbedingt einen shared_ptr auf this brauchst gibt es std::enable_shared_from_this. Aber hier reicht eigentlich ein normaler Pointer. Iteratoren sind nur so lange gültig wie die Struktur zu der sie gehören, fertig. Macht die STL auch so.



  • Stimmt, da hast du recht! Einen Speicherbereich implizit zu zerstören, der auf dem Stack liegt, macht einfach keinen Sinn!

    Danke, da hätte ich lange gebraucht, um darauf zu kommen!

    L. G.



  • Im übrigen hat dein Code auch noch ein Memory Leak. Du hast mit deinen shared_ptr eine zyklische Abhängigkeit zwischen Parent und Child aufgebaut. Der Parent Pointer kann ein ganz normaler Pointer sein, da das Child ja mindestens so lange lebt wie das Parent. Außerdem gibt es keinen Grund für shared_ptr überall. Du kopierst diese ständig unnötig und hast dadurch Overhead für den Reference Counter. Hier wäre unique_ptr für den Besitz und normale Pointer für das drumherum sinnvoller. Ist aber vermutlich größere Arbeit das umzustellen.



  • Vor allem funktioniert das Balancing nicht, wenn ich das aktiviere... 😞



  • Wenn du was aktivierst?



  • Sorry, dumm ausgedrückt. 🙂

    Zeile 68:

    p = balance(p);
    

    Hatte ich erst mal auskommentiert, um zu sehen, dass das InOrder-Feature ohne Balancing funktioniert. Das tut es. Mit Balancing funktioniert es nicht mehr. Ich hatte versucht beim Balancing die neuen Eltern richtig zu setzen, allerdings stimmt das Ergebnis einfach nicht.

    #include "avltree.h"
    #include <iostream>
    
    int main()
    {
        AVLTree<int> tree;
    
        for (int i = 0; i < 4; ++i) {
            tree.insert(i);
        }
    
        for (int elem : tree) {
            std::cout << elem << ",";
        }
    
        std::cout << std::endl;
    
        return 0;
    }
    

    Liefert:

    0,3,1,2,
    


  • Hm, schon das Balancing ist kaputt. Ich habe mal das Parent-Feature deaktiviert.

    #ifndef AVLTREE_H
    #define AVLTREE_H
    
    #include <memory>
    #include <algorithm>
    #include <assert.h>
    #include <iterator>
    #include <iostream>
    
    template <typename T>
    class AVLTree
    {
    private:
      class Node
      {
      public:
        int height = 0;
        T value;
    
        std::shared_ptr<Node> left = nullptr;
        std::shared_ptr<Node> right = nullptr;
        //std::shared_ptr<Node> parent = nullptr;
    
        Node(T v)
          : value(v)
        {
        }
    
        // Kleiner-Ordnung
        bool operator<(const T& _value) const { return value < _value; }
      };
    
      std::shared_ptr<Node> root = nullptr;
    
      int getHeight(std::shared_ptr<Node> p)
      {
        if (p == nullptr)
          return -1;
        else
          return p->height;
      }
    
      int getBalance(std::shared_ptr<Node> p)
      {
        if (p == nullptr)
          return 0;
        else
          return getHeight(p->right) - getHeight(p->left);
      }
    
      std::shared_ptr<Node> insertR(T value, std::shared_ptr<Node> p)
      {
        if (p == nullptr) {
          p = std::make_shared<Node>(value);
        } else if (value < p->value) {
          std::shared_ptr<Node> temp = insertR(value, p->left);
          p->left = temp;
          //temp->parent = p;
        } else if (value > p->value) {
          std::shared_ptr<Node> temp = insertR(value, p->right);
          p->right = temp;
          //temp->parent = p;
        }
    
        p = balance(p);
    
        return p;
      }
    
      std::shared_ptr<Node> balance(std::shared_ptr<Node> p)
      {
        if (p == nullptr)
          return nullptr;
    
        p->height = std::max(getHeight(p->left), getHeight(p->right)) + 1;
    
        if (getBalance(p) == -2) {
          if (getBalance(p->left) <= 0)
            p = rotateRight(p);
          else
            p = rotateLeftRight(p);
        } else if (getBalance(p) == 2) {
          if (getBalance(p->right) >= 0)
            p = rotateLeft(p);
          else
            p = rotateRightLeft(p);
        }
    
        return p;
      }
    
      std::shared_ptr<Node> rotateRight(std::shared_ptr<Node> p)
      {
        assert(p->left != nullptr);
    
        std::shared_ptr<Node> q = p->left;
        p->left = q->right;
        q->right = p;
    
        p->height = std::max(getHeight(p->left), getHeight(p->right)) + 1;
        q->height = std::max(getHeight(q->left), getHeight(q->right)) + 1;
    
        //q->parent = p->parent;
        //q->right->parent = p;
        //p->parent = q;
    
        return q;
      }
    
      void inOrder(std::shared_ptr<Node> p)
      {
          if (p!=nullptr)
          {
              inOrder(p->left);
              std::cout<< p->value <<"\t";
              inOrder(p->right);
          }
      }
    
      std::shared_ptr<Node> rotateLeft(std::shared_ptr<Node> p)
      {
        assert(p->right != nullptr);
    
        std::shared_ptr<Node> q = p->right;
        p->right = q->left;
        q->left = p;
    
        p->height = std::max(getHeight(p->left), getHeight(p->right)) + 1;
        q->height = std::max(getHeight(q->left), getHeight(q->right)) + 1;
    /*
        q->parent = p->parent;
        q->left->parent = p;
        p->parent = q;*/
    
        return q;
      }
    
      std::shared_ptr<Node> rotateLeftRight(std::shared_ptr<Node> p)
      {
        assert(p->left != nullptr);
    
        p->left = rotateLeft(p->left);
        return rotateRight(p);
      }
    
      std::shared_ptr<Node> rotateRightLeft(std::shared_ptr<Node> p)
      {
        assert(p->right != nullptr);
    
        p->right = rotateRight(p->right);
        return rotateLeft(p);
      }
    
      bool contains(T value, std::shared_ptr<Node> p)
      {
        if (p == nullptr) {
          return false;
        } else {
          if (value < *p) {
            contains(value, p->left);
          } else {
            if (value > *p) {
              contains(value, p->right);
            } else {
              return true;
            }
          }
        }
      }
    
      std::shared_ptr<Node> findMax(std::shared_ptr<Node> p)
      {
        if (p == nullptr) {
          return p;
        } else {
          while (p->right != nullptr) {
            p = p->right;
          }
          return p;
        }
      }
    
      std::shared_ptr<Node> findMin(std::shared_ptr<Node> p)
      {
        if (p == nullptr) {
          return p;
        } else {
          while (p->left != nullptr) {
            p = p->left;
          }
          return p;
        }
      }
    
      class iterator : std::iterator<std::forward_iterator_tag, T>
      {
        AVLTree* tree;
        std::shared_ptr<Node> node;
    
      private:
        /*std::shared_ptr<Node> inOrderSuccessor(std::shared_ptr<Node> n)
        {
          // step 1 of the above algorithm
          if (n->right != nullptr)
            return tree->findMin(n->right);
    
          // step 2 of the above algorithm
          std::shared_ptr<Node> p = n->parent;
          while (p != nullptr && n == p->right) {
            n = p;
            p = p->parent;
          }
          return p;
        }*/
    
      public:
        explicit iterator()
          : tree(nullptr)
          , node(nullptr)
        {
        }
    
        explicit iterator(AVLTree* tree)
          : tree(tree)
        {
          node = tree->findMin(tree->root);
        }
    
        T& operator*() { return node->value; }
    
        iterator& operator++()
        {
          if (node != nullptr) {
            //node = inOrderSuccessor(node);
          }
    
          return *this;
        }
    
        iterator operator++(int)
        {
          iterator tmp = *this;
          ++*this;
          return tmp;
        }
    
        void printInOrder() {
            tree->inOrder(tree->root);
        }
    
        bool operator==(const iterator& other) const { return node == other.node; }
        bool operator!=(const iterator& other) const { return node != other.node; }
      };
    
    public:
      iterator begin() { return iterator(this); }
      iterator end() { return iterator(); }
    
      void insert(T value)
      {
        if (root == nullptr) {
          root = std::make_shared<Node>(value);
        } else {
          insertR(value, root);
        }
      }
    
      bool contains(T value) { return contains(value, root); }
    
      T findMax() { findMax(root)->value; }
    };
    
    #endif // AVLTREE_H
    
    #include "avltree.h"
    #include <iostream>
    
    int main()
    {
        AVLTree<int> tree;
    
        for (int i = 0; i < 10; ++i) {
            tree.insert(i);
        }
    
        tree.begin().printInOrder();
    
    /*
        for (int elem : tree) {
            std::cout << elem << ",";
        }*/
    
        std::cout << std::endl;
    
        return 0;
    }
    

    Gibt hier "0 9" aus.



  • Hab mich gerade 30 min durch deinen Code geschlagen. Der Fehler (oder wenigstens einer) ist in deiner void insert(T value) Funktion. Dort muss es

    root = insertR(value, root);
    

    heißen, da sich der Wurzelknoten bei einem balance ja auch ändern kann. Mit der kleine Änderung scheint es zu funktionieren.



  • Vielen Dank! Du erleichterst mir das Leben!
    Vll. fragst du dich, weshalb ich einen eigenen AVL-Baum mache. Das ist eigentlich nicht zu Übungszwecken gedacht, sondern ich brauche einen AVL-Baum der einen 2D-Range-Search kann. D. h., das soll mal ein 2D-AVL-Baum werden, aber erst mal, muss das für 1D funktionieren. Eigentlich will ich damit geometrische Algorithmen implementieren (das ist die eigentliche Übung), aber erst mal brauche ich diesen doofen Baum. 😛

    Der Code wird OpenSource sein, auch weil du mir geholfen hast.

    Der neueste Stand funktioniert leider nicht mehr, wenn der Baum linkslastig wird. Er gibt dann rekursiv 4,3 aus. Werde wohl weiter brüten.

    #include "avltree.h"
    #include <iostream>
    
    int main()
    {
        AVLTree<int> tree;
    
        for (int i = 6; i > 0; --i) {
            tree.insert(i);
        }
    
        for (int elem : tree) {
            std::cout << elem << ",";
        }
    
        std::cout << std::endl;
    
        return 0;
    }
    

    Den neuesten Code findest du hier:

    https://github.com/StefanoD/AVLTree

    L. G.



  • sebi707 schrieb:

    Hab mich gerade 30 min durch deinen Code geschlagen. Der Fehler (oder wenigstens einer) ist in deiner void insert(T value) Funktion. Dort muss es

    root = insertR(value, root);
    

    heißen, da sich der Wurzelknoten bei einem balance ja auch ändern kann. Mit der kleine Änderung scheint es zu funktionieren.

    👍 👍 👍


  • Mod

    👍



  • Der Code scheint jetzt zu funktionieren! Die Parents wurden nicht richtig gesetzt.

    Jetzt würde ich den Code ein bisschen auräumen, d. h. von shared_ptr auf unique_ptr umsteigen. Verbesserungsvorschläge sind gerne erwünscht. Wie gesagt: Das ist OpenSource und soll der Allgemeinheit dienen. Im Internet findet man leider kaum AVL-Bäume mit Templates und Iteratoren, geschweigedenn mit Range-Search!

    L. G.



  • Habe nun auf Raw-Pointer umgestellt, weil der Code mit unique_ptr ganz schön hässlich wurde. Da musste man ein .get() aufrufen, wenn man den unique_ptr an eine Funktion übergeben wollte und man musste einen unique_ptr erstellen und anschließend moven, wenn man eine Zuweisung an einen unique_ptr machen wollte.

    Allerdings sagt valgrind:

    ==10262== 
    ==10262== HEAP SUMMARY:
    ==10262==     in use at exit: 91,308 bytes in 7 blocks
    ==10262==   total heap usage: 1,010 allocs, 1,003 frees, 123,412 bytes allocated
    ==10262== 
    ==10262== 4 bytes in 1 blocks are still reachable in loss record 1 of 7
    ==10262==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10262==    by 0x8CE8F22: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CE9464: g_private_get (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CC173C: g_slice_alloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C937ED: g_hash_table_new_full (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CB470A: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C75E58: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x40105B9: call_init.part.0 (dl-init.c:72)
    ==10262==    by 0x40106CA: call_init (dl-init.c:30)
    ==10262==    by 0x40106CA: _dl_init (dl-init.c:120)
    ==10262==    by 0x4000D09: ??? (in /lib/x86_64-linux-gnu/ld-2.21.so)
    ==10262== 
    ==10262== 32 bytes in 1 blocks are still reachable in loss record 2 of 7
    ==10262==    at 0x4C2DB95: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10262==    by 0x8CAA5D0: g_malloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C93854: g_hash_table_new_full (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CB470A: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C75E58: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x40105B9: call_init.part.0 (dl-init.c:72)
    ==10262==    by 0x40106CA: call_init (dl-init.c:30)
    ==10262==    by 0x40106CA: _dl_init (dl-init.c:120)
    ==10262==    by 0x4000D09: ??? (in /lib/x86_64-linux-gnu/ld-2.21.so)
    ==10262== 
    ==10262== 64 bytes in 1 blocks are still reachable in loss record 3 of 7
    ==10262==    at 0x4C2DB95: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10262==    by 0x8CAA5D0: g_malloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C9383F: g_hash_table_new_full (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CB470A: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C75E58: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x40105B9: call_init.part.0 (dl-init.c:72)
    ==10262==    by 0x40106CA: call_init (dl-init.c:30)
    ==10262==    by 0x40106CA: _dl_init (dl-init.c:120)
    ==10262==    by 0x4000D09: ??? (in /lib/x86_64-linux-gnu/ld-2.21.so)
    ==10262== 
    ==10262== 88 bytes in 1 blocks are still reachable in loss record 4 of 7
    ==10262==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10262==    by 0x8CAA578: g_malloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CC1762: g_slice_alloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C937ED: g_hash_table_new_full (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CB470A: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C75E58: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x40105B9: call_init.part.0 (dl-init.c:72)
    ==10262==    by 0x40106CA: call_init (dl-init.c:30)
    ==10262==    by 0x40106CA: _dl_init (dl-init.c:120)
    ==10262==    by 0x4000D09: ??? (in /lib/x86_64-linux-gnu/ld-2.21.so)
    ==10262== 
    ==10262== 2,032 bytes in 1 blocks are still reachable in loss record 5 of 7
    ==10262==    at 0x4C2DB95: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10262==    by 0x8CAA5D0: g_malloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CC19CB: g_slice_alloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C937ED: g_hash_table_new_full (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CB470A: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C75E58: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x40105B9: call_init.part.0 (dl-init.c:72)
    ==10262==    by 0x40106CA: call_init (dl-init.c:30)
    ==10262==    by 0x40106CA: _dl_init (dl-init.c:120)
    ==10262==    by 0x4000D09: ??? (in /lib/x86_64-linux-gnu/ld-2.21.so)
    ==10262== 
    ==10262== 16,384 bytes in 1 blocks are still reachable in loss record 6 of 7
    ==10262==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10262==    by 0x8CAA578: g_malloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8CB471B: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x8C75E58: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4600.1)
    ==10262==    by 0x40105B9: call_init.part.0 (dl-init.c:72)
    ==10262==    by 0x40106CA: call_init (dl-init.c:30)
    ==10262==    by 0x40106CA: _dl_init (dl-init.c:120)
    ==10262==    by 0x4000D09: ??? (in /lib/x86_64-linux-gnu/ld-2.21.so)
    ==10262== 
    ==10262== 72,704 bytes in 1 blocks are still reachable in loss record 7 of 7
    ==10262==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10262==    by 0x58261FF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
    ==10262==    by 0x40105B9: call_init.part.0 (dl-init.c:72)
    ==10262==    by 0x40106CA: call_init (dl-init.c:30)
    ==10262==    by 0x40106CA: _dl_init (dl-init.c:120)
    ==10262==    by 0x4000D09: ??? (in /lib/x86_64-linux-gnu/ld-2.21.so)
    ==10262== 
    ==10262== LEAK SUMMARY:
    ==10262==    definitely lost: 0 bytes in 0 blocks
    ==10262==    indirectly lost: 0 bytes in 0 blocks
    ==10262==      possibly lost: 0 bytes in 0 blocks
    ==10262==    still reachable: 91,308 bytes in 7 blocks
    ==10262==         suppressed: 0 bytes in 0 blocks
    ==10262== 
    ==10262== For counts of detected and suppressed errors, rerun with: -v
    ==10262== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    

    Also 1,010 allocs und 1,003 frees, heißt es gab Memory-Leaks? So wie es ausschaut jedoch nicht in meinem Code, sondern irgendwo in den System-Libs. Sehe ich das richtig?!

    L. G.


Anmelden zum Antworten