small object allocator: Aufruf von Destruktor notwendig?



  • dd++ schrieb:

    d.h. bei einer Klasse, deren Destrukor keine Auswirkung (side effects) hat, kann man den Speicher feigeben, ohne den Destrukor aufzurufen. konkret hat auch MFC ~CObject() keine Auswirkung, siehe atlmfc\include\afx.h und atlmfc\include\afx.inl

    Ja, aber wenn

    for (...)
      data[i]::~type();
    delete[] pool;
    

    gleich

    for (...)
      /* nothing to do, it's trivial */;
    delete[] pool
    

    ist, macht der optimierende Compiler daraus

    /* nothing to destruct */
    delete[] pool;
    

    Du sparst dir also nichts.

    dd++ schrieb:

    von dem std::vector kann ich in diesem Anwendungfall aus mehreren Gründen nur abraten.

    Für solche Fälle gibt es auch std::deque .



  • Nö, wird nicht ganz wegoptimiert.

    Aus

    struct Foo
    {
        int bar;
    
        Foo() : bar(0) { }
        ~Foo() { bar = 1; }
    };
    
    Foo* mem = (Foo*)std::malloc(sizeof(Foo) * 1000);
    for(size_t i = 0; i < 1000; ++i)
        new(mem + i) Foo;
    
    ... Code ...
    
    for(size_t i = 0; i < 1000; ++i)
        mem[i].~Foo();
    std::free(mem);
    

    wird der Compiler allerhöchstens machen:

    Foo* mem = (Foo*)std::malloc(sizeof(Foo) * 1000);
    std::fill((int*)mem, (int*)mem + 1000, 0);
    
    ... Code ...
    
    std::fill((int*)mem, (int*)mem + 1000, 1);
    std::free(mem);
    

    Ich halte es für sehr unwarscheinlich dass der Compiler weiß dass nach dem Aufruf von std::free der Speicher nicht mehr genutzt wird und der Aufruf der Destruktoren unnötig ist.



  • Ethon schrieb:

    Nö, wird nicht ganz wegoptimiert.

    1. Mein GCC optimiert den vollständig weg. Alles was bleibt ist ein free().
    2. Es ging um trivially destructible Typen, den Destruktor wegzulassen ist hier UB.
    3. So ein Destruktor hat keinen Sinn.



  • jamenschenskind schrieb:

    2. Es ging um trivially destructible Typen, den Destruktor wegzulassen ist hier UB.

    geh noch mal in die Schule und lern lesen. vielleicht findest du dann auch heraus, wie man sich hier im Forum anmeldet

    im ersten Post geht es um eine Klasse, die von MFC CObject erbt. diese Klasse wiederum hat einen leeren virtuellen Destruktor. laut 12.4 Destructors 5 ist das ein nicht-trivialer Destruktor. dieser Destruktor hat aber offensichtlich keinen Effekt oder anders ausgedrückt keinen Einfluß auf den weiteren Programmablauf. laut 3.8 Object lifetime 4 kann man den Speicher dieses Objekts freigeben, ohne den Destruktor aufzurufen



  • Das Problem sollte nun gelöst sein. Memory pool war das Stichwort. Ich verwende nun boost::object_pool statt Loki::SmallObjAllocator. Die Destruktoren werden jetzt aufgerufen (beim Zerstören des pools).

    Das das nicht Aufrufen des Destruktors unter bestimmten Umständen "legal" ist, ist auf jeden Fall gut zu wissen.

    Danke an alle für die Hilfe 🙂



  • einspruch schrieb:

    dd++ schrieb:

    von dem std::vector kann ich in diesem Anwendungfall aus mehreren Gründen nur abraten.

    Für solche Fälle gibt es auch std::deque .

    std::deque wäre cool, wenn man die Page-Size einstellen könnte. Die ist nämlich typischerweise viel zu klein wenn es darum geht auf Geschwindigkeit zu optimieren.
    std::deque ist halt wirklich darauf optimiert eine double ended queue zu sein, und nicht ein Pool/Small-Object-Allocator.


Anmelden zum Antworten