Operator delete überladen



  • Ich habe ein Programm geschrieben und mit dem GCC Compiler übersetzt. Dieses Programm testet meine eigenen Operatoren. Mir ist aufgefallen, dass der globale Operator delete nicht nur den allozierten Speicher frei gibt, sondern auch die Pointer, die auf die Speicheradresse zeigen.
    Ich habe mein delete nur soweit implementieren können, dass der allozierte Speicher freigegeben wird.
    Wie kann ich das Verhalten des globalen delete erreichen?

    Die Auskommentierte "if" Bedingung in der Implementierung des delete- Operators verhindert, dass der globale Operator delete aufgerufen wird. Wird das Programm so ausgeführt, wird nur der Speicher freigegeben. Entfernt man die Kommentarzeichen, wird der globale Operator delete aufgerufen und auch die Variablen gelöscht.
    Erkennbar wird das, wenn der Task Manager nebenbei läuft und man sich die Größe der Auslagerungsdatei anguckt.

    Unter VC lässt sich der Code nicht übersetzten.

    #include <iostream>
    #include <stdlib.h>
    #include <conio.h>
    
    using namespace std;
    
    class buffer{
    public:
        buffer(){
            pi = new int;
        }
        ~buffer(){
            delete pi;
        }
        static void *operator new(size_t);
        static void *operator new[](size_t);
        static void operator delete(void *, size_t);
        static void operator delete[](void *, size_t);
    private:
        int *pi;
    };
    
    void *buffer::operator new(size_t size){
        void *memory;
        if(size == 0)
            size = 1;
        for( ; ; ){
            try{
                memory = ::operator new(size);
                cout << "Mein new - operator" << endl;
                cout << "Size von memory ist " << size << " Byte" << endl << endl;
                return memory;
            }
            catch(bad_alloc){
                new_handler globalHandler = set_new_handler(0);
                set_new_handler(globalHandler);
                if (globalHandler)
                      (*globalHandler)();	
                else throw bad_alloc();
            }
        }
    }
    
    void *buffer::operator new[](size_t size){
        void *memory;
        if(size == 0)
            size = 1;
        for( ; ; ){
            try{
                memory = :: operator new[](size);
                cout << "Mein new[] - operator" << endl;
                cout << "Size von memory ist " << size << " Byte" << endl << endl;
                return memory;
            }
            catch(bad_alloc){
                new_handler globalHandler = set_new_handler(0);
                set_new_handler(globalHandler);
                if (globalHandler)
                      (*globalHandler)();	
                else throw bad_alloc();
            }
        }
    }
    
    void buffer::operator delete(void *rawMemory, size_t size){
        if(rawMemory == 0)
            return;
        if(size != sizeof(buffer)){
            ::operator delete(rawMemory);
            return;
        }
        cout << "Mein delete - operator" << endl;
        cout << "Size von *rawMemory ist " << size << " Byte" << endl;
        size = 0;
        return;
    }
    
    void buffer::operator delete[](void *rawMemory, size_t size){
        if(rawMemory == 0)
            return;
    /*    if(size != sizeof(buffer)){
            cout << "Size von *rawMemory ist " << size << " Byte" << endl;
            cout << "Jetzt wird das globale delete[] aufgerufen" << endl;
            ::operator delete[](rawMemory);
            return;
        }
    */    cout << "Mein delete[] - operator" << endl;
        cout << "Size von *rawMemory ist " << size << " Byte" << endl;
        size = 0;
        return;
    }
    
    int main(int argc, char *argv[]){
    
        buffer *b = new buffer;
        delete b;
        cout << endl;
        buffer *c = new buffer[0];
        delete []c;
        cout << endl;
        buffer *d = new buffer[10000000];
        delete []d;
        system("PAUSE");	
        return 0;
    }
    


  • Variablen werden nicht "geloescht". Sie sind solange gueltig, bis ihr Scope
    verlassen wird. Deiner Aussage zur folge (so wie ich sie interpretiere), wuerde
    folgendes nicht gehn:

    char *Test = new char[50];
    delete[] Test;
    Test = new char[60]; //2
    

    Waere die Variable "geloescht", wuerde (2) nicht funktionieren. Das ist aber
    nicht der Fall. Wenn ich das richtig sehe, geben deine op delete/delete[] auch
    gar keinen Speicher frei, sondern setzen lediglich die lokale Variable 'size'
    auf 0.

    Hoffe ich hab hier nichts falsch verstanden.

    mfg
    v R



  • Es stimmt, ich setze die Variable size auf 0.
    Dadurch wird der Speicher doch freigegeben, oder?
    Wie kann man den sonst Speicher freigeben?



  • Spawn schrieb:

    Es stimmt, ich setze die Variable size auf 0.
    Dadurch wird der Speicher doch freigegeben, oder?
    Wie kann man den sonst Speicher freigeben?

    Ne, dadurch wird der Speicher natuerlich nicht freigegeben. Du _musst_ den
    globalen op delete callen.

    mfg
    v R



  • Naja, ich überlasse das erst mal wieder dem globalen delete, aber hast du das Programm mal laufen lassen?
    Indem man size auf 0 setzt, wird tatsächlich Speicher freigegeben.
    Beobachte mal die Größe der Auslagerungsdatei



  • die auslagerungsdatei ist in solchen fällen nicht sehr genau, es kann auch zu ganz normalen schwankungen gekommen sein.

    was auch immer, von der size lässt man die finger,und zwar aus folgendem grund:
    [theorie]
    ein pointer zeigt auf einen bestimmten speicherbereich, dieser ist im operator new durch size_t size dargestellt.
    wenn man nun size auf 0 setzt,wird sich der pointer wie ein void pointer verhalten: er zeigt auf eine speicheraddresse, man kann aber sonst nichts mit ihm machen.
    der speicher wird aber auch nicht freigegeben,da rein theoretisch dem freeMem noch mitgeteilt werden müsste, dass die Speicheraddresse nun nicht mehr gebraucht wird.
    {/theorie]


Anmelden zum Antworten