simples memcpy



  • Hi,

    Ich bin gerade dabei ein simples memcpy selber zu programmieren, aber irgendwie
    funktioniert es nicht.
    Ich denke es hat etwas damit zu tun, dass ich auf Speicher zugreife obwohl ich es nicht darf, aber ich weiß nich wo.

    typedef unsigned long long ui64; //64 Bit unsigned integer
    
    ui64 ui64GetSize(char *cpChars)
    {
            if(cpChars==NULL)
                return (0);
            else
            {
                ui64 ui64Size=0;
    
                for(;cpChars[ui64Size]!='\0';ui64Size++)
                {
                    ;//Do Nothing
                }
    
                return (ui64Size+1);
            }
    }
    
    //GetSize funktioniert einwandfrei
    
    void vCopyChars(char *cpSource,char *cpDestination)
    {
        if(cpSource==NULL) //gucken ob cpSource überhaupt auf etwas zeigt
            return;
        else
        {
            ui64 ui64SourceSize=ui64GetSize(cpSource);//Länge von cpSource
    
            cpDestination=new char[ui64SourceSize];//cpDestination auf die größe einstellen
    
            for(ui64 ui64Ticks=0;ui64Ticks<ui64SourceSize;ui64Ticks++)
            {
                cpDestination[ui64Ticks]=cpSource[ui64Ticks];//cpDestination füllen
            }
    
        }
    }
    

  • Mod

    gnrtu schrieb:

    cpDestination=new char[ui64SourceSize];//cpDestination auf die größe einstellen
    

    wozu soll das gut sein?

    sinnvoller als ein 64bit typ vor, dürfte hier außerdem die verwendung von std::size_t sein.



  • Mhhhh joa, aber das ist doch ef egal oder?

    Außerdem finde ich wens es 64 Bit integers gibt sollte man se auch benutzen und nicht nur 32 Bit.

    http://tigcc.ticalc.org/doc/stddef.html#size_t



  • gnrtu schrieb:

    Mhhhh joa, aber das ist doch ef egal oder?

    Außerdem finde ich wens es 64 Bit integers gibt sollte man se auch benutzen und nicht nur 32 Bit.

    http://tigcc.ticalc.org/doc/stddef.html#size_t

    Du solltest eigentlich nie mehr als size_t an speicher resevieren.



  • Warum?

    is das net eg off topic?



  • gnrtu schrieb:

    Ich bin gerade dabei ein simples memcpy selber zu programmieren

    Das was du programmiert hast, ist eher strcpy. memcpy interessiert der Inhalt der Quelle überhaupt nicht. Dh, du kannst dir die ui64GetSize Funktion vollkommen sparen, die nützt dir nix. Damit die Länge bekannt ist, hat memcpy einen weiteren Parameter. Der fehlt deiner vCopyChars Funktion. Und memcpy reserviert intern auch keinen Speicher, das überlässt du mal besser dem Client. Wenn der angibt, dass er n Chars kopieren will, dann hat er auch dafür zu sorgen, dass der Zielbereich mindestens n Chars gross ist.

    btw:
    Nichts für ungut, aber versuche deinen Stil zu vereinfachen. Von deinem Code bekomme ich leichte Kopfschmerzen. Dieses ganze ui64... Zeug ist recht unleserlich, und zudem der falsche Datentyp. Für Speichergrössen gibt es size_t. Dann kannst du, wenn du denn unbedingt UN verwenden willst, einfach n... schreiben.



  • gnrtu schrieb:

    Warum?

    mehr als 2 gb hat erstens fast keiner, und zweitens musst du bedenken, dass ein 32 bit system auch nur 4 gb haben kann (ich glaub sogar praktisch auch nur 2gb). selbst wenn jemand 4 gb hat, heißt das nicht das das betriebsystem einem programm alles zurverfügung stellt.

    Und auf einem 64bit system ist ein long auch 8 byte groß, oder?

    mfg.



  • std::size_t hat eine "geeignete" Größe. Auf einem 64-Bit-System sollte das dann 64 Bit sein. Auf einem 32-Bit-System 32 Bit, also immer so groß wie nötig.

    Aber nun zu deinem eigentlichen Problem. Du reservierst Speicher und merkst Dir die Adresse in der Variablen cpDestination. Am Ende der Funktion wird die Variable verworfen. Du hast einen Memoryleak. Wahrscheinlich wolltest Du den Pointer als Referenz übergeben. Besser wäre, ihn einfach als Rückgabewert zurück zu liefern.

    Ausserdem kann man die Standardfunktionen, wie strlen und strcpy doch verwenden, wenn es die schon gibt.

    char* vCopyChars(char *cpSource)
    {
        if(cpSource==0) //gucken ob cpSource überhaupt auf etwas zeigt
            return 0;
    
        std::size_t s = std::strlen(cpSource);
    
        char *cpDestination=new char[s];//cpDestination auf die Größe einstellen
        std::strcpy(cpDestination, cpSource);
    }
    


  • joomoo schrieb:

    Und auf einem 64bit system ist ein long auch 8 byte groß, oder?

    Das kommt ganz darauf an, welches Datenmodell verwendet wird. Unter Win64 ist long zB weiterhin 32 Bit, da LLP64 verwendet wird. Streng genommen gibt es also unter Windows keinen 64 Bit C++ Datentyp, da nur long long 64 Bit breit ist, dies aber kein C++ Datentyp ist. Ein weiterer Grund size_t zu verwenden, denn da kümmert sich die Implementation schon drum, dass grössentechnisch alles passt.



  • ok, ihr habt mich überzeugt 🙂 .

    Aber mal ne andere Frage?

    Wenn man speicher in einer Funktion anfordert, wird er dann am Ende der Funktion wieder freigegeben?

    Bsp:

    char *p1,*p2;
    
    void p2mem(char *p)
    {
        p=new char[6];
    }
    
    p1="Hallo";
    
    strcpy(p2,p1);
    

    Hier kommt ein fehler, dass man unberechtigt auf Speicher zugreift.

    char *p1,*p2;
    
    p1="Hallo";
    
    p2=new char[6];
    
    strcpy(p2,p1);
    

    Jetzt klappt alles.

    Daraus würde ich schließen, dass reservierter Speicher am Ende des Blockes wieder freigegeben wird, aber man verändert ja eine Variable von außerhalb über Zeiger.



  • gnrtu schrieb:

    ok, ihr habt mich überzeugt 🙂 .

    Aber mal ne andere Frage?

    Wenn man speicher in einer Funktion anfordert, wird er dann am Ende der Funktion wieder freigegeben?

    Nein.

    Bsp:

    char *p1,*p2;
    
    void p2mem(char *p)
    {
        p=new char[6];
    }
    
    p1="Hallo";
    
    strcpy(p2,p1);
    

    Hier kommt ein fehler, dass man unberechtigt auf Speicher zugreift.

    Das liegt daran, dass du nur die Variable p änderst, die ja nur in p2men() gültig ist. Die Variable p2 wird nicht geändert. Dies lässt sich mit ner referenz lösen:

    void p2mem(char*& p); // ich glaub etwa so, bin nicht ganz sicher
    

    mfg.



  • Ahhhhh....
    Es funktioniert mit **.

    mfg



  • Das ist dann aber ein Doppelzeiger und nicht die in C++ üblicherweise genutzte Referenz 😉



  • Refernzen mag ich net 😉


Anmelden zum Antworten