Löschen bzw. wieder freigeben von speicher



  • hey @all,

    ich habe mir ein NodeSystem gebaut, in dem ich bei jeder Node 1 Parent habe, jedoch jeder Node n childs haben kann.

    Nun zu meinem Problem... Entweder ich stehe gerade gewaltig am Schlauch oder der Compiler hat ein Problem.

    Ich lösche irgendeinen Node* mit "delete node".

    Im Destructor der Node habe ich folgendes:

    Node::~Node() {
      for(std::vector<Node*>::iterator it = this->lchilds.begin(); it != this->lchilds.end(); ++it) {
        if((*it) != NULL) {
          delete &(*it);
          (*it) = NULL;
          it = this->lchilds.erase((*it));
        }
      }
    }
    

    Und genau hier hauts mich auf, da dieses "(*it) = NULL" nicht bewirkt das der Pointer auf NULL gesetzt wird und somit in this if anweisung geht und versucht das ganze nochmals zu löschen.

    Habe ich da grundlegend was falsches gedacht? Achja, zukünftig hatte ich statt dem std::vector eine std::list. Jedoch liefert mir die std::list nur einen const_iterator zurück.

    Kann mir bitte jemand bei diesem Problem helfen?

    Vielen Dank im Voraus
    LG _freeze_

    P.S.: Blöde Frage, aber was muss ich in einem Destructor noch alles zerstören? Habe noch Elemente vom Typ time_t, std::string und int's


  • Mod

    Node::~Node() {
      for(std::vector<Node*>::iterator it = this->lchilds.begin(); it != this->lchilds.end(); ++it) {
        if((*it) != NULL) {
          delete &(*it); // damit würdest du versuchen, das Zeigerobjekt an Stelle des Objektes, auf dass der Zeiger zeigt zu löschen
          (*it) = NULL; // nicht falsch, aber da der vector sowieso im Anschluss nur noch zerstört wird auch nicht notwendig
          it = this->lchilds.erase((*it)); // das ist überflüssig, Zeitverschwendung, bei vector sehr teuer, und du müsstest auf das ++it verzichten, andernfalls werden Elemente übersprungen
        }
      }
    }
    

    Es genügt

    for(std::vector<Node*>::iterator it = this->lchilds.begin(); it != this->lchilds.end(); ++it)
        if((*it) != NULL)
          delete *it;
    

    Noch besser dürfte ein Pointercontainer sein oder wenigstens checked_delete

    for_each(lchilds.begin(),lchilds.end(),boost::checked_deleter<Node>());
    


  • freeze schrieb:

    Node::~Node() {
      for(std::vector<Node*>::iterator it = this->lchilds.begin(); it != this->lchilds.end(); ++it) {
        if((*it) != NULL) { // Überprüfung auf NULL /0 muss nicht sein. delete 0 geht auch!
          delete &(*it);
          (*it) = NULL;
          it = this->lchilds.erase((*it)); // hier erase (it) machen
        }
      }
    }
    

    Du musst grundsätzlich alles aufräumen, was du mit new angefordert hast. int's usw. gehören ja nicht dazu.



  • delete auf einen nullzeiger ist nicht verboten. die abfrage und das nullsetzen kannst du dir daher sparen. allerdings schlägt das delete fehl, weil du versuchst, einen zeiger von node zu löschen. du willst aber den node selbst löschen. also

    Node::~Node()
    {
      for(std::vector<Node*>::iterator it = this->lchilds.begin(); it != this->lchilds.end(); ++it)
      {
          delete *it;
          it = this->lchilds.erase(it); //aber da du lchilds sowieso nicht verwendest, ist das eigentlich sinnlos.
      }
    }
    

    grundsatz: für jedes new ein delete.
    also für jede von *dir* dynamisch (zur laufzeit) angeforderte ressource musst du sicherstellen, dass *du* sie auch entsprechend wieder freigibst.
    beim löschen eines iterators aus einer std::list kannst du list.erase(it++) verwenden (wie bei assoziativen containern).



  • Vielen herzlichen Dank für Eure schnellen Antworten
    @camper
    Jedoch produziert folgender Code von Dir

    for(std::vector<Node*>::iterator it = this->lchilds.begin(); it != this->lchilds.end(); ++it)
        if((*it) != NULL)
          delete *it;
    

    eine "Unbehandelte Ausnahme": Zugriffsverletzung beim Lesen an Position 0xfeeefeee.

    Lg _freeze_



  • alle Nodes, die du in die liste/vector eingefügt hast, müssen mit new angefordert worden sein. /edit: und dürfen nicht an anderer stelle schonmal gelöscht worden sein.



  • ok, habs jetzt wie folgt hinbekommen:

    for(std::vector<Node*>::iterator it = this->lchilds.begin(); it != this->lchilds.end();) {// ++it)
      if(*it != NULL) {
        delete *it;
        *it = NULL;
      }
      it = this->lchilds.erase(it);
    }
    

    Jedoch wird mein Speicher nicht wieder freigegeben: Am Anfang der Applikation schaut der Speicher wie folgt aus:

    Mem Usage: 2016
    VM Size: 748

    Danach fügte ich ein paar Nodes ein:

    Mem Usage: 2548
    VM Size: 776

    und nachdem ich nun alles brav gelöscht habe

    Mem Usage: 2548
    VM Size: 776

    Was passt da noch nicht?

    Lg _freeze_



  • du zeigst uns nur den halben code (nur die freigabe) und beachtest hinweise nicht: du brauchst das erase für den iterator nicht. du musst nur für jeden neuen Node sicherstellen, dass er gelöscht wird.

    for (std::vector<Node*>::iterator it = lchilds.begin(); it != lchdils.end(); ++it)
       delete *it;
    

    das reicht völlig.
    wenn du noch zeigst, wo und wie du den speicher anforderst 🙂

    btw. nur weil du den speicher freigibst, muss das nicht heißen, dass der speicher auch tatsächlich freigegeben wird. es kann genauso gut sein, dass delete intern wartet, bis ein block (oder wie auch immer der speicher verwaltet wird) frei ist und dann alles auf einmal freigibt. oder dass der freigegebene speicher in einem puffer liegt, so dass new nicht gleich vom betriebssystem neuen speicher anfordern muss, sondern einfach den freigegebenen verwendet.

    wenn du hundertprozentig sicherstellen willst, dass *du* alle objekte gelöscht hast, dann verpasse Node einfach einen objektzähler.

    class Node
    {
       static int count;
    public:
       Node () { count++; }
       Node (Node const&) { count++; }
    
       ~Node () { count--; }
    }
    
    int Node::count;
    
    int main ()
    {
       do_something_important();
       assert (Node::count == 0);
    }
    


  • queer_boy schrieb:

    du zeigst uns nur den halben code

    So schaut bei mir eine Node aus:
    node_data_types.h

    #ifndef NODE_DATA_TYPES_H
    #define NODE_DATA_TYPES_H
    
    #include <iostream>
    typedef unsigned int n_uint;
    //typedef unsigned int n_i64;
    typedef long long n_i64;
    #if defined(__LP64__) or defined(_LP64) // Conversion 64bit -> 32 Bit
        typedef unsigned int  n_size_t;
        typedef int           n_long;
    #else // Original Datatypes for 32bit systems
        typedef size_t        n_size_t;
        typedef long          n_long;
    #endif
    
    namespace NDB {
        /*!
          \enum Access Right Definition
        */
        enum AccessRightDef { User, Group, Other };
        /*!
          \enum Access Right
        */
        enum AccessRights { None = 0, Execute = 1, Write = 2, Read = 4 };
    
        enum NodeDataType { // Basic Node Data Type
            NDT_UNKNOWN = -1,
            NDT_MASTER = 0,
            NDT_ROOT,
            NDT_BOOLEAN,
            NDT_STRING,
            NDT_INTEGER,
            NDT_DOUBLE,
            NDT_DATE,
            NDT_TIME,
            NDT_DATETIME,
            NDT_DOCUMENT,
            NDT_FOLDER_GREEN,
            NDT_FOLDER_RED,
            NDT_FOLDER_BLUE,
            NDT_FOLDER_YELLOW,
            NDT_FOLDER_GREY,
            NDT_FOLDER_ORANGE,
            NDT_FOLDER_PURPLE,
        };
    
        enum EdgeType { // Basic Edge Type
            ET_UNKNOWN = -1,
            ET_DATA = 0,
            ET_APPLICATION,
            ET_SYSTEM,
            ET_TOOLTIP,
            ET_ICON,
            ET_CBITEM,
            ET_DOCUMENT_TYPE,
        };
    };
    
    #endif
    

    node.h

    #ifndef NODE_H
    #define NODE_H
    
    #include <iostream>
    #include <string>
    #include <set>
    #include <map>
    #include <list>
    
    #include "node_data_types.h"
    
    //typedef long long   n_i64;
    namespace NDB {
        //class QTNode;
        class Node;
    
        typedef std::list<Node*> NodeList;
        typedef std::map<n_i64, Node*> NodeMap;
        typedef std::list<n_i64> IDList;
        typedef std::set<n_i64> ChildList;
    
        /*!
          \enum Access Right Definition
        */
        /*enum AccessRightDef { User, Group, Other };
        /*!
          \enum Access Right
        */
        /*enum AccessRights { None = 0, Execute = 1, Write = 2, Read = 4 };*/
    
        //! Node
        /*!
          This class represent a node.
        */
    
        class Node { // : public QTNode {
        private:
            time_t created_ts;
            time_t modified_ts;
            time_t accessed_ts;
            n_i64 id;
            //unsigned int type;
            NodeDataType type;
            std::string alias;
            std::string name;
            std::string value;
            n_i64 parent;
            n_i64 user_id;
            n_i64 group_id;
            n_i64 access_right_user;
            n_i64 access_right_group;
            n_i64 access_right_other;
            Node* p_parent;
            std::set<n_i64> childs;
            std::list<Node*> lchilds;
    //        NodeList lchilds;
            //std::map<n_i64, Node*> lchilds;
            n_i64 link_parent;
            std::set<n_i64> links;
            n_i64 flags;
            EdgeType edge_type;
            time_t now();
    
        public:
            Node();
            //Node(n_i64 _id, n_uint _type = 1000, std::string _alias = "", std::string _name = "",
            Node(n_i64 _id, NodeDataType _type = NDT_ROOT, EdgeType _edge_type = ET_DATA, std::string _alias = "", std::string _name = "",
                 std::string _value = "", n_i64 _parent = -1, n_i64 _lparent = -1, n_i64 _flags = 0);
            ~Node();
            //void setType(n_uint _type);
            //! To set the type of a node.
            /*!
              \param _type an NodeDataType.
              \sa Node(), ~Node()
            */
            void setType(NodeDataType _type);
            //! To set the alias of a node.
            /*!
              \param _alias an std::string.
              \sa Node(), ~Node()
            */
            void setAlias(std::string _alias);
            //! To set the name of a node.
            /*!
              \param _name an std::string.
              \sa Node(), ~Node()
            */
            void setName(std::string _name);
            //! To set the value of a node.
            /*!
              \param _value an std::string.
              \sa Node(), ~Node()
            */
            void setValue(std::string _value);
            //! To set the access rights of a node.
            /*!
              \param _def an AccessRightDef.
              \param _rights an AccessRights.
              \sa Node(), ~Node()
            */
            void setAccessRight(AccessRightDef _def, AccessRights _rights);
            //! To set the user id of a node.
            /*!
              \param _id an n_i64.
              \sa Node(), ~Node()
            */
            void setUserID(n_i64 _id);
            //! To set the group id of a node.
            /*!
              \param _id an n_i64.
              \sa Node(), ~Node()
            */
            void setGroupID(n_i64 _id);
            //! To set the id of a node.
            /*!
              \param _id an n_i64.
              \sa Node(), ~Node()
            */
            void setID(n_i64 _id);
            //! To set the edge type of a node.
            /*!
              \param _edge_type an EdgeType.
              \sa Node(), ~Node()
            */
            void setEdgeType(EdgeType _edge_type);
            //! To set the modified timestamp of a node.
            void setModifiedTS();
            //! To set the accessed timestamp of a node.
            void setAccessedTS();
            //! To set the created timestamp of a node.
            void setCreatedTS();
            //! To set the modified timestamp of a node.
            void setModifiedTS(time_t _value);
            //! To set the accessed timestamp of a node.
            void setAccessedTS(time_t _value);
            //! To set the created timestamp of a node.
            void setCreatedTS(time_t _value);
            /*!
              \return The type of a node as a NodeDataType
            */
            NodeDataType getType();
            //n_uint getType();
            /*!
              \return The alias of a node as an std::string
            */
            std::string getAlias();
            /*!
              \return The name of a node as an std::string
            */
            std::string getName();
            /*!
              \return The value of a node as an std::string
            */
            std::string getValue();
            /*!
              \param _def an AccessRightDef.
              \return The access right of a node of the specified \@_def
            */
            n_i64 getAccessRight(AccessRightDef _def);
            /*!
              \return The user id of a node as a n_i64
            */
            n_i64 getUserID();
            /*!
              \return The group id of a node as a n_i64
            */
            n_i64 getGroupID();
            /*!
              \return The id of a node as a n_i64
            */
            n_i64 getID();
            /*!
              \return The edge type of a node on which the node is connected to the parent as an EdgeType
            */
            EdgeType getEdgeType();
            /*!
              \return The parent id of a node as a n_i64
            */
            n_i64 getParentID();
            /*!
              \return The flags of a node as a n_i64
            */
            n_i64 getFlags();
            /*!
              \return The parent of a node as a node pointer
            */
            Node* getParent();
            /*!
              \return The childs of a node as a NodeList
            */
            NodeList getLChilds();
            /*!
              @deprecated { use \sa getLChilds() instead }
              \return A list of node child id's as a std::set<n_i64>
            */
            std::set<n_i64> getChilds();
            /*!
              \return The modified timestamp of a node as a time_t
            */
            time_t getModifiedTS();
            /*!
              \return The access timestamp of a node as a time_t
            */
            time_t getAccessedTS();
            /*!
              \return The created timestamp of a node as a time_t
            */
            time_t getCreatedTS();
            bool hasChilds(Node *_node);
            /*! Append the specified node (_node) as a child to the current node;
              \param _node a pointer of a node.
              \return a pointer of the current node as a node pointer
            */
            Node* appendChild(Node *_node);
            friend std::ostream& operator << (std::ostream& strm, Node* node);
            //std::ostream& operator << (std::ostream& strm, const Node& node);
            //std::ostream& operator << (const Node& node);
        //	const ClientSocket& operator << (const std::string&) const;
        };
    };
    #endif
    

    node.cpp

    #include "node.h"
    #include "node_data_types.h"
    
    using namespace std;
    
    namespace NDB {
    
    Node::Node() {
        id = -1;
        type = NDT_ROOT;//1000;    // Root
        alias = "";
        name = "";
        value = "";
        parent = -1;
        childs.erase(childs.begin(), childs.end());
        links.erase(links.begin(), links.end());
        flags = 0;
        p_parent = NULL;
        edge_type = ET_DATA;
        this->access_right_user = Execute | Write | Read;
        this->access_right_group = None;
        this->access_right_other = None;
        this->user_id = 1;
        this->group_id = 1;
        this->created_ts = now();
        this->modified_ts = now();
        this->accessed_ts = now();
    }
    
    //Node::Node(n_i64 _id, n_uint _type, std::string _alias, std::string _name,
    Node::Node(n_i64 _id, NodeDataType _type, EdgeType _edge_type, std::string _alias, std::string _name,
               std::string _value, n_i64 _parent, n_i64 _lparent, n_i64 _flags) : id(_id),
               type(_type), edge_type(_edge_type), alias(_alias), name(_name), value(_value), parent(_parent),
               link_parent(_lparent), flags(_flags) {
        p_parent = NULL;
        this->access_right_user = Execute | Write | Read;
        this->access_right_group = None;
        this->access_right_other = None;
        this->user_id = 1;
        this->group_id = 1;
        this->created_ts = now();
        this->modified_ts = now();
        this->accessed_ts = now();
    }
    
    Node::~Node() {
    	for(NodeList::iterator it = this->lchilds.begin(); it != this->lchilds.end();) {
    		if(*it != NULL) {
    			delete *it;
    			*it = NULL;
    		}
    		it = this->lchilds.erase(it);
    	}
    }
    
    time_t Node::now() {
      time_t rawtime;
      time(&rawtime);
      return rawtime;
    }
    
    //void Node::setType(n_uint _type) {
    void Node::setType(NodeDataType _type) {
        this->type = _type;
        setModifiedTS();
    }
    
    void Node::setAlias(std::string _alias) {
        this->alias = _alias;
        setModifiedTS();
    }
    
    void Node::setName(std::string _name) {
        this->name = _name;
        setModifiedTS();
    }
    
    void Node::setValue(std::string _value) {
        this->value = _value;
        setModifiedTS();
    }
    
    void Node::setAccessRight(AccessRightDef _def, AccessRights _rights) {
        switch(_def) {
            case User:
                this->access_right_user = _rights;
                break;
            case Group:
                this->access_right_group = _rights;
                break;
            case Other:
                this->access_right_other = _rights;
                break;
        }
        setModifiedTS();
    }
    
    void Node::setUserID(n_i64 _id) {
        this->user_id = _id;
    }
    
    void Node::setGroupID(n_i64 _id) {
        this->group_id = _id;
    }
    
    void Node::setID(n_i64 _id) {
        this->id = _id;
    }
    
    void Node::setEdgeType(EdgeType _edge_type) {
        this->edge_type = _edge_type;
    }
    
    void Node::setModifiedTS() {
        this->modified_ts = now();
    }
    
    void Node::setAccessedTS() {
        this->accessed_ts = now();
    }
    
    void Node::setCreatedTS() {
        this->created_ts = now();
    }
    
    void Node::setModifiedTS(time_t _value) {
        this->modified_ts = _value;
    }
    
    void Node::setAccessedTS(time_t _value) {
        this->accessed_ts = _value;
    }
    
    void Node::setCreatedTS(time_t _value) {
        this->created_ts = _value;
    }
    
    //n_uint Node::getType() {
    NodeDataType Node::getType() {
        setAccessedTS();
        return this->type;
    }
    
    std::string Node::getAlias() {
        setAccessedTS();
        return this->alias;
    }
    
    std::string Node::getName() {
        setAccessedTS();
        return this->name;
    }
    
    std::string Node::getValue() {
        setAccessedTS();
        return this->value;
    }
    
    n_i64 Node::getAccessRight(AccessRightDef _def) {
        setAccessedTS();
        switch(_def) {
            case User:
                return this->access_right_user;
                break;
            case Group:
                return this->access_right_group;
                break;
            case Other:
                return this->access_right_other;
                break;
        }
        return 0;
    }
    
    n_i64 Node::getUserID() {
        setAccessedTS();
        return this->user_id;
    }
    
    n_i64 Node::getGroupID() {
        setAccessedTS();
        return this->group_id;
    }
    
    n_i64 Node::getID() {
        setAccessedTS();
        return this->id;
    }
    
    EdgeType Node::getEdgeType() {
        setAccessedTS();
        return this->edge_type;
    }
    
    n_i64 Node::getParentID() {
        setAccessedTS();
        return this->parent;
    }
    
    n_i64 Node::getFlags() {
        setAccessedTS();
        return this->flags;
    }
    
    Node* Node::getParent() {
        setAccessedTS();
        return this->p_parent;
    }
    
    NodeList Node::getLChilds() {
        setAccessedTS();
        return this->lchilds;
    }
    
    std::set<n_i64> Node::getChilds() {
        setAccessedTS();
        return this->childs;
    }
    
    time_t Node::getModifiedTS() {
        return this->modified_ts;
    }
    
    time_t Node::getAccessedTS() {
        return this->accessed_ts;
    }
    
    time_t Node::getCreatedTS() {
        return this->created_ts;
    }
    
    bool Node::hasChilds(Node *_node) {
        if(this->childs.find(_node->id) != this->childs.end())
            return true;
        return false;
    }
    
    Node* Node::appendChild(Node *_node) {
        _node->parent = this->id;
    
        std::pair< std::set<n_i64>::iterator, bool > pr;
        pr = this->childs.insert(_node->id);
    
        if(pr.second) {
            _node->p_parent = (Node*)this;
            this->lchilds.push_back(_node);
        }
            //this->lchilds.push_back(&_node);
            //this->lchilds.push_back(*_node);
            //this->lchilds.insert(_node);
            //this->lchilds.insert(make_pair(_node->id, _node));
    
        setModifiedTS();
        return (Node*)this;
    }
    
    //const ClientSocket& ClientSocket::operator << (const std::string& s) const {
    //std::ostream& Node::operator << (const Node& node) {
    std::ostream& operator << (std::ostream& strm, Node* node) {
        strm << "Node-ID: " << node->getID() << endl;
        strm << "Node-Type: " << node->getType() << endl;
        strm << "Node-Alias: " << node->getAlias() << endl;
        strm << "Node-Name: " << node->getName() << endl;
        strm << "Node-Value: " << node->getValue() << endl;
        strm << "Node-Parent: " << node->getParentID() << endl;
        std::set<n_i64> childs = node->getChilds();
        if(!childs.empty()) {
            strm << "Node-Childs: ";
            for(std::set<n_i64>::iterator iter = childs.begin();
                iter != childs.end();
                ++iter) {
               if(iter != childs.end() && iter != childs.begin())
                   strm << ",";
                strm << (*iter);
            }
            strm << endl;
        }
    	return strm;
    }
    };
    

    Und hier ein beispiel was nicht geht

    #include "node_data_types.h"
    #include "node.h"
    //#include <cassert>
    using namespace NDB;
    
    int main(int argc, char *argv[]) {
        Node *node_main_config = new Node(1);
        Node *node_system = new Node(2);
        Node *node_system_users = new Node(3);
        Node *node_user1 = new Node(4);
        Node *node_user_rights1 = new Node(5);
        Node *node_user_rights_user1 = new Node(6);
        Node *node_user_rights_group1 = new Node(7);
        Node *node_user_rights_other1 = new Node(8);
        Node *node_user_password1 = new Node(9);
    
        node_system->appendChild(node_system_users);
        node_system_users->appendChild(node_user1);
        node_user1->appendChild(node_user_password1);
        node_user1->appendChild(node_user_rights1);
        node_user_rights1->appendChild(node_user_rights_user1);
        node_user_rights1->appendChild(node_user_rights_group1);
        node_user_rights1->appendChild(node_user_rights_other1);
        node_main_config->appendChild(node_system);
    
        delete node_main_config;
        //node_main_config = NULL;
    
    //	assert (Node::count == 0);
    
        if(node_system != NULL) {
          delete node_system;              // ----------> Hier passiert der Fehler
          node_system = NULL;
        }
    	return 0;
    }
    

    Obwohl "node_main_config" und alle childs darunter "deleted" worden sind hüpft er in die if Anweisung, da ich noch immer eine Speicheradresse habe (Die wohl nicht mehr gültig ist).
    Was kann ich tun, damit "node_system" ebenfalls nach dem Löschen von "node_main_config" NULL ist?

    Lg _freeze_



  • @queer_boy

    Ich habe jetzt Deinen counter noch eingebaut. 👍 Spitzen Tipp.
    Laut counter werden alle gelöscht, jedoch sind die nodes dennoch nicht NULL 🙄

    Mach ich da was falsch? Hatte auch schon probiert Referenzen von Pointern an die Methode appendChild() zu geben. Leider auch ohne Erfolg

    Lg _freeze_



  • dir muss klar sein, dass wenn du einen Node* zur Verwaltung an deinen container (in dem fall ein mother-Node) gibst, du diesen nicht mehr löschen musst, da dein container dies macht.
    d.h. an der stelle

    if(node_system != NULL) {
          delete node_system;              // ----------> Hier passiert der Fehler
          node_system = NULL;
        }
    

    gibt es an der speicherstelle, auf die node_system zeigt, kein objekt mehr, da dieses (und jedes andere node!) im destruktor von node_main_config zerstört wird.
    der zeiger "node_system" zeigt zwar noch auf den speicherbereich, wo ein Node einmal war, doch dieser Node wurde im destruktor von node_main_config bereits zerstört - zweimal delete auf dieselbe speicherstelle fliegt dir aber um die ohren.

    die alternative ist, dass du das speichermanagement gar nicht den einzelnen nodes überlässt, sondern selbst (außerhalb von Node) in die hand nimmst.

    btw. ohne mir den code ins letzte detail anzusehen, würde wahrscheinlich eine funktion à la:

    void foo (Node n)
    {
    }
    

    bei ihrem aufruf zu einem absturz führen.
    implementiere einen passenden copy-constructor (oder lass diese art von speichermanagement aus node raus).



  • freeze schrieb:

    ...

    Jedoch wird mein Speicher nicht wieder freigegeben: ...

    Was passt da noch nicht?...

    Dein "Speicher-Meßgerät" !
    Die Freigabe von Speicher zeigt sich nicht automatisch in jedem beliebigen Tool. Betriebssysteme haben üblicherweise seeehr komplexe Scheduler-Mechanismen, die dann auch sowas wie Caching umsetzen (schonmal aufgefallen, dass z.B. Word sehr viel schneller startet, wenn man es direkt vorher schonmal laufen hatte ?).
    Wirklich sichere Aussagen bekommst Du jedenfalls nicht, wenn Du nur von "Außen" draufschaust, sondern da musst Du schon ein spezielles "Speicherleck-such-Programm" 😉

    Gruß,

    Simon2.


Log in to reply