Pointer auf Datenobjekte in einem vector heap speichern.



  • Also "sinnfrei, aber nicht undefiniert". Ich bezweifle daher immer noch, dass sowas wie

    vector<int> v1 = ...;
    vector<int> v2 = move(v1);
    vector<int> v3 = move(v1);
    

    im STL-Quellcode vorkommt.

    btw. @krümelkacker: Wie sieht es denn mit einer Selbst-Move-Zuweisung aus? Ist die erlaubt? Edit: Zumindest bei der VS2010-STL wird eine Selbstzuweisung explizit abgefangen im Move-Assignment Operator von vector . Also wird man das wohl brauchen..



  • life schrieb:

    btw. @krümelkacker: Wie sieht es denn mit einer Selbst-Move-Zuweisung aus? Ist die erlaubt?

    Mir fallen zwar keine Situationen ein, in denen so ein Fall auftreten kann, ohne dass man absichtlich a=move(a); schreibt, aber ich denke schon, dass das eine Klasse verkraften können sollte.

    life schrieb:

    Edit: Zumindest bei der VS2010-STL wird eine Selbstzuweisung explizit abgefangen im Move-Assignment Operator von vector . Also wird man das wohl brauchen..

    Es gibt, wie gesagt, noch den Copy&Swap-Trick. Das ist nicht unbedingt die effizienteste Lösung in allen Fällen, aber relativ einfach und man kann kaum etwas falsch machen:

    class Klasse
    {
      ...
    public:
      ...
      Klasse(Klasse const&); // copy ctor
      Klasse(Klasse     &&); // move ctor
      ~Klasse();
    
      void swap(Klasse& other);
    
      Klasse& operator=(Klasse tmp) {  // <-- pass-by-value ist Absicht
        this->swap(tmp);
        return *this;
      }
      ...
    };
    


  • krümelkacker schrieb:

    life schrieb:

    btw. @krümelkacker: Wie sieht es denn mit einer Selbst-Move-Zuweisung aus? Ist die erlaubt?

    Mir fallen zwar keine Situationen ein, in denen so ein Fall auftreten kann, ohne dass man absichtlich a=move(a); schreibt, aber ich denke schon, dass das eine Klasse verkraften können sollte.

    Hmm...

    void swap(Foo&& a,Foo &&b){
       Foo tmp=move(a);
       a=move(b);
       b=move(tmp);
    }
    

    Hoffentlich stimmt das so.

    Also passiert's bei jedem swap(a,a). Wo hab ich sowas bloß gesehen? Ich erinnere mich, daß ich bei manchen Algos mich darauf verlassen habe, daß swap mit sich selbst erlaubt ist und damit ein if gespart habe.



  • Hallo.

    Ich habe das mal mit meinen anderen Beispielgraphen ausprobiert und von den 4 riesigen Graphen die ich habe funktionierts nur für einen.

    Bei dem anderem erhalte ich einen Fehler beim "MoveConstructor" (das war doch jetzt richtig oder? :-))

    MovableVertex(MovableVertex&& vertex) : ref(vertex.ref)
        {
          //std::cout << "Copied " << ref->number << " from " << &vertex << " to " << this << std::endl;
    
          assert(ref != 0);
          assert(&vertex != this);
          ref->revref = this; // <==== Hier krachts
          vertex.ref = 0;  
        }
    

    Speicherzugriffsfehler.
    Beim debuggen habe ich dann festgestellt dass ref zwar != 0 ist, aber irgendwie auch ungültig ist, darum bringen hier die ganzen 0-Checks ja rein gar nix.
    Der Debugger sagt:

    (gdb) print ref
    $1 = (Vertex ) 0x20011
    (gdb) print
    ref
    Cannot access memory at address 0x20011

    Wie kann so etwas zustande kommen?
    Wie gesagt das passiert bei 3 von 4 riesigen Graphen.



  • Lass es durch valgrind laufen.



  • Habs versucht aber irgendwie scheint das unter openSUSE 11.2 nicht zu funktionieren. Ich versuch das mal zum laufen zu bringen und dann kommen Ergebnisse.



  • volkard schrieb:

    Hmm...

    void swap(Foo&& a,Foo &&b){
       Foo tmp=move(a);
       a=move(b);
       b=move(tmp);
    }
    

    Hoffentlich stimmt das so.

    Ja, die zweite Zeile wäre dann bei &a==&b eine "Selbst-Move-Zuweisung". Allerdings müsste es heißen swap(Foo& a,Foo& b) . Dass die Rvalue-Referenzen sich mit Lvalue-Ausdrücken initialisieren lassen stimmt seit 1 1/2 Jahre nicht mehr. Leider ist so gut wie kein Rvalue-Referenz-Artikel im Netz auf dem aktuellen Stand. Es gibt eigentlich nur eine Artikel-Serie, die die aktuellen Regeln erklärt (beachte: Die Liste der Artikel auf der verlinkten Seite ist chronologisch verkehrt herum).

    kk



  • valgrind geht irgendwie nicht.
    Der sagt mit fehlen die debug-info's zu glibc, aber die hab ich jetzt alle installiert, sowie die devel-Packete und debugsources aber hat alles nix gebracht.
    Gibts vielleicht noch was anderes in der Richtung?



  • Max3000 schrieb:

    valgrind geht irgendwie nicht.
    Der sagt mit fehlen die debug-info's zu glibc, aber die hab ich jetzt alle installiert, sowie die devel-Packete und debugsources aber hat alles nix gebracht.
    Gibts vielleicht noch was anderes in der Richtung?

    Such nach dem Problem bei google. Da gibt es eine Lösung zu. Ich glaube valgrind-Pakete aus einem Repository.

    Eventuell: https://bugzilla.novell.com/show_bug.cgi?id=545721



  • Die Seiten habe ich mir alle schon durchgelesen.
    Müssen die Versionen von debug und normalem Packet übereinstimmen?
    Bei einem hab ich die 2.10.irgendwas und debug hab ich die 2.11.irgendwas.



  • Ah jetzt gehts. Hab ein Repo gefunden was die selbe Version anbietet.
    Das kommt dabei raus:

    > valgrind --leak-check=yes ./DijkstraBinary scotland_small.dat
    ==7787== Memcheck, a memory error detector
    ==7787== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
    ==7787== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
    ==7787== Command: ./DijkstraBinary scotland_small.dat
    ==7787==
    K-Shortest Path Algorithm

    Loading scotland_small.dat
    Vertices loaded...
    Edges loaded...
    Vertices: 16384
    Edges: 65025

    Building shortest path tree...
    0% 10 20 30 40 50 60 70 80 90 100%
    |----|----|----|----|----|----|----|----|----|----|
    ==7787== Invalid read of size 8
    ==7787== at 0x402694: MovableVertex::MovableVertex(MovableVertex&&) (DijkstraBinary.cpp:174)
    ==7787== by 0x40302E: void std::push_heap<MovableVertex*>(MovableVertex*, MovableVertex*) (stl_heap.h:168)
    ==7787== by 0x401D18: main (DijkstraBinary.cpp:348)
    ==7787== Address 0x72a4b38 is 8 bytes before a block of size 131,072 alloc'd
    ==7787== at 0x4C249DC: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==7787== by 0x40565E: __gnu_cxx::new_allocator<MovableVertex>::allocate(unsigned long, void const*) (new_allocator.h:89)
    ==7787== by 0x404B9C: std::_Vector_base<MovableVertex, std::allocator<MovableVertex> >::_M_allocate(unsigned long) (stl_vector.h:140)
    ==7787== by 0x403BA9: MovableVertex* std::vector<MovableVertex, std::allocator<MovableVertex> >::_M_allocate_and_copy<std::move_iterator<MovableVertex*> >(unsigned long, std::move_iterator<MovableVertex*>, std::move_iterator<MovableVertex*>) (stl_vector.h:963)
    ==7787== by 0x402CD8: std::vector<MovableVertex, std::allocator<MovableVertex> >::reserve(unsigned long) (vector.tcc:74)
    ==7787== by 0x401AAC: main (DijkstraBinary.cpp:306)
    ==7787==
    DijkstraBinary: DijkstraBinary.cpp:178: MovableVertex::MovableVertex(MovableVertex&&): Assertion `ref != 0' failed.
    ==7787==
    ==7787== HEAP SUMMARY:
    ==7787== in use at exit: 5,366,322 bytes in 114,183 blocks
    ==7787== total heap usage: 244,770 allocs, 130,587 frees, 10,514,919 bytes allocated
    ==7787==
    ==7787== 26 bytes in 1 blocks are possibly lost in loss record 1 of 11
    ==7787== at 0x4C249DC: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==7787== by 0x4ECCAF0: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.12)
    ==7787== by 0x4ECD724: ??? (in /usr/lib64/libstdc++.so.6.0.12)
    ==7787== by 0x4ECD8C1: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.12)
    ==7787== by 0x401850: main (DijkstraBinary.cpp:292)
    ==7787==
    ==7787== LEAK SUMMARY:
    ==7787== definitely lost: 0 bytes in 0 blocks
    ==7787== indirectly lost: 0 bytes in 0 blocks
    ==7787== possibly lost: 26 bytes in 1 blocks
    ==7787== still reachable: 5,366,296 bytes in 114,182 blocks
    ==7787== suppressed: 0 bytes in 0 blocks
    ==7787== Reachable blocks (those to which a pointer was found) are not shown.
    ==7787== To see them, rerun with: --leak-check=full --show-reachable=yes
    ==7787==
    ==7787== For counts of detected and suppressed errors, rerun with: -v
    ==7787== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)
    Abgebrochen



  • Der Fehler sagt wohl alles:

    main (DijkstraBinary.cpp:348)

    Address 0x72a4b38 is 8 bytes before a block of size 131,072 alloc'd



  • Sorry aber damit kann ich noch nix anfangen.
    Was soll das bedeuten?
    Dass 8 bytes vor einem Block von 131.072 bytes allokiert wurde?


  • Mod

    max3001 schrieb:

    Sorry aber damit kann ich noch nix anfangen.
    Was soll das bedeuten?
    Dass 8 bytes vor einem Block von 131.072 bytes allokiert wurde?

    Nein, dass heißt, dass auf nicht reservierten Speicher zugegriffen wurde. Die Adresse des Zugriffs liegt aber 8 Bytes vor einem reservierten Block. Dies deutet auf einen fehlerhaften (möglicherweise negativen) Index beim Zugriff hin.



  • Ah ich glaub ichs habs gefunden. Ich hatte drin:

    std::push_heap(&heap[0], headOfCurrentEdge->revref);
    

    aber es muss heißen

    std::push_heap(&heap[0], headOfCurrentEdge->revref + 1);
    

    so hatte ich das zwar auch ursprünglich aber irgendwie hab ichs vergessen wieder umzustellen.
    Wieder was gelernt: TODO-Comments setzen :D.
    Jetzt klappt schonmal eine Beispieldatei mehr.
    Ich probier noch alle anderen aus und meld mich dann wieder.
    Danke für den Hinweis.


Anmelden zum Antworten