Eine mir nicht ganz erklärliche Speicherzugriffsverletzung

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Benutzeravatar
Bebu
Beiträge: 562
Registriert: Mi Okt 21, 2009 6:19 pm
Wohnort: In der Nähe von Salzburg - Bin aber kein Österreicher!

Eine mir nicht ganz erklärliche Speicherzugriffsverletzung

Beitrag von Bebu » Di Jan 10, 2012 11:42 pm

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.
Wer immer nach dem Unerreichbaren jagt, der wird irgendwann auf die Schnauze fallen!

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: Eine mir nicht ganz erklärliche Speicherzugriffsverletzu

Beitrag von Kerli » Mi Jan 11, 2012 12:41 am

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.
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Eine mir nicht ganz erklärliche Speicherzugriffsverletzu

Beitrag von fat-lobyte » Mi Jan 11, 2012 1:38 pm

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);
+        }
     };
 
     /**
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Bebu
Beiträge: 562
Registriert: Mi Okt 21, 2009 6:19 pm
Wohnort: In der Nähe von Salzburg - Bin aber kein Österreicher!

Re: Eine mir nicht ganz erklärliche Speicherzugriffsverletzu

Beitrag von Bebu » Mi Jan 11, 2012 6:49 pm

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 :?
Wer immer nach dem Unerreichbaren jagt, der wird irgendwann auf die Schnauze fallen!

Antworten