Seite 1 von 1

Eine mir nicht ganz erklärliche Speicherzugriffsverletzung

Verfasst: Di Jan 10, 2012 11:42 pm
von Bebu
Hallo, ich bastle mal wieder an Dedupe und baue gerade etwas, damit der User Entscheidungen bzw. der Duplikate fällen kann. Dazu haben ich dieses Konstrukt gebaut:

Code: Alles auswählen

typedef std::function<void( Dedupe::Core::DupHandle )> KeyFunction;

class Keys
    {
      public:
      Keys() : StoredKeys(), StringToStore( "" ) { }

      std::string & GetInput() { return StringToStore; }

      private:

      class Proxy
      {
        public:
        Proxy( Keys &CallingClass ) : Instance( CallingClass ) {}

        Proxy & operator() ( std::string Key, KeyFunction KeyFunc )
        {
          std::unique_ptr<Proxy> Next( new Proxy( Instance ));

          Instance.StoredKeys[ Key ] = KeyFunc;

          return *Next;
        }

        private:
        Keys &Instance;
      };

      std::map<std::string,KeyFunction> StoredKeys;
      std::string StringToStore;

      public:
      Proxy & AddKeys()
      {
        std::unique_ptr<Proxy> First( new Proxy( *this ));

        return *First;
      }
    };
Benutzt wird es so:

Code: Alles auswählen

auto Keep = [] ( Dedupe::Core::DupHandle Handle )
             { Handle.second = Dedupe::Core::Keep; };

   auto MarkAsKeep = [] ( Dedupe::Core::DupHandle Handle )
            { Handle.second = Dedupe::Core::MarkAsKeep; };

   auto Delete = [] ( Dedupe::Core::DupHandle Handle )
                 { Handle.second = Dedupe::Core::Delete; };

   Message << Dups.size() << " duplicate Groups are found\n";

   Dedupe::CLI::Keys Keys;

   Keys.AddKeys() ( "y", Keep )
                  ( "n", Delete )
                  ( "m", MarkAsKeep );
Diese Zeile löst den Speicherfehler aus:

Code: Alles auswählen

 Instance.StoredKeys[ Key ] = KeyFunc;
Die Frage ist für mich nur, warum. Ich hatte an dieser Stelle einen Vector stehen, der nur einen String enthielt. der push_back() hat problemlos funktioniert. Es hat vermutlich irgendetwas mit dem Pair-Template zu tun, das intern verwendet wird, ein Vector der ein solches Pair enthält schmiert auch ab.

Re: Eine mir nicht ganz erklärliche Speicherzugriffsverletzu

Verfasst: Mi Jan 11, 2012 12:41 am
von Kerli
Du solltest bedenken dass alle Smartpointer ihren Pointee zerstören sobald sie ihren Gültigkeitsbereich verlassen.

Code: Alles auswählen

std::unique_ptr<Proxy> First( new Proxy( *this ));
return *First; // Hier wird First zerstört, da die Funktion verlassen wird
Außerdem würde ich so kleine und kurzlebige Objekte wie es deine Proxies sind eher am Stack anlegen als am Heap.

Re: Eine mir nicht ganz erklärliche Speicherzugriffsverletzu

Verfasst: Mi Jan 11, 2012 1:38 pm
von fat-lobyte
Kerli hat geschrieben:Außerdem würde ich so kleine und kurzlebige Objekte wie es deine Proxies sind eher am Stack anlegen als am Heap.
Gerade das sollte das Problem lösen.
Wenn man aus den Heap-Objekten Stack-Objekte macht, und aus den zurückgegeben Refernzen einfach Werte, dann funktionierts:

Code: Alles auswählen

Index: userinterface/cli/ui.h
===================================================================
--- userinterface/cli/ui.h	(Revision 254)
+++ userinterface/cli/ui.h	(Arbeitskopie)
@@ -33,13 +33,13 @@
         public:
         Proxy( Keys &CallingClass ) : Instance( CallingClass ) {}
 
-        Proxy & operator() ( std::string Key, KeyFunction KeyFunc )
+        Proxy operator() ( std::string Key, KeyFunction KeyFunc )
         {
-          std::unique_ptr<Proxy> Next( new Proxy( Instance ));
+          Proxy Next(Instance);
 
           Instance.StoredKeys[ Key ] = KeyFunc;
 
-          return *Next;
+          return Next;
         }
 
         private:
@@ -50,12 +50,10 @@
       std::string StringToStore;
 
       public:
-      Proxy & AddKeys()
-      {
-        std::unique_ptr<Proxy> First( new Proxy( *this ));
-
-        return *First;
-      }
+        Proxy AddKeys()
+        {
+          return Proxy(*this);
+        }
     };
 
     /**

Re: Eine mir nicht ganz erklärliche Speicherzugriffsverletzu

Verfasst: Mi Jan 11, 2012 6:49 pm
von Bebu
Danke für die Hilfe, dass das Problem so einfach zu lösen ist, hätte ich nicht gedacht. Ich war schon mal fast so weit wie fat-lobyte, habe aber Referenzen zurückgeliefert und deswegen eine Warnung bekommen. Deswegen habe ich angefangen mit den Pointern rumzuspielen. Ich fange langsam an um Ecken zu denken, die gar nicht da sind :?