Problem mit new()

cesupa

Erfahrenes Mitglied
Ich hab da ein Problem mit new(). Unzwar möchte ich einen char-buffer generieren der sich jedesmal wenn die Funktion aufgerufen wird, vergrößert. Das heißt also: Wenn die Funktion das erste mal aufgerufen wird, wird besagter char-buffer auf 1024 Bytes (die Größe wird berechnet und in eine Variable vom Typ long geschrieben, als Beipiel nehme ich hier 1024) vergrößert:

Code:
charbuffer=new char[1024];
//Anweisungen
delete[] charbuffer;

wird die Funktion zum zweiten mal aufgerufen vergrößert sich der buffer auf 3072:

Code:
charbuffer=new char[3072];
//Anweisungen
delete[] charbuffer;

das ganze geht zunächst so weiter.
Windows gibt jetzt aber bevor es das zweite Mal Speicher für den Buffer reserviert (also der buffer von 1024 auf 3072 Bytes vergrößert werden soll) einen Fehler aus: "written" kann auf den Speicher 0x00000...nicht ausgeführt werden...

Ich hab leider keine Ahnung warum das passiert? Was genau geschieht denn da Speicherintern? Wie kann ich den Fehler beheben?

Gruß
cesupa
 
1. Lesen bildet. es gibt tatsächlich sowas wie Dokumentationen die beschreiben wie new und delete arbeiten. Kann nie schaden sich sowas mal anzusehen, erst recht nicht wenns es sich um derartige Basisfunktionen wie new/delete handelt.

2. Du vegrößerst nicht den Buffer beim 2ten Aufruf, du legst einen neuen Buffer an und überschreibst den alten Pointer mit der Adresse des neuen Buffers.

3. No sourcode, no help.... Das ist so wie wenn dir jemand die Farbe Rot zeigt und dann fragt, welche anderen Farben in dem Bild noch fehlen. Wir können jetzt zwar alle lustig raten was du alles falsch machst, aber über Spekulationen geht das nicht hinaus. Hier meine: Du machst etwas falsch mit dem Buffer.
 
Also gut, das gnaze geschieht in der Klasse Buffer, die ich geschrieben hab:

Code:
void buffer::add(const char* c2,long len)
{  
          this->buf2=new char[this->lenb];                  //Speicher reservieren mit der Größe des Puffers (vergrößert sich jedesmal: 1024 -> 3072 -> usw.) = FEHLER
     this->lenb2=this->lenb;        
     mcpy(this->buf2,this->buf,0,this->lenb);                  //Kopie von Puffer machen
    
 this->lenb2+=len;                                          //neue Puffer Größe
     this->buf=new char[this->lenb2];                           //Puffer mit neuer Größe generieren
      mcpy(this->buf,this->buf2,0,this->lenb);                   //Puffer-Kopie in Puffer kopieren
     mcpy(this->buf,c2,this->lenb,this->lenb2);                 //String in neuen Puffer dazukopieren
     
     this->lenb+=this->lenb2;                                                        
     this->lenb2=0;     
     delete[] this->buf2;                                
   
 }

Code:
void buffer::mcpy(char* c1,const char* c2,long start,long size)
{
     long z=0;
     for(start;start<=size;start++)
     {
     c1[start]=c2[z];
     z++;
     }
 }

Das ganze wird so aufgerufen:

Code:
buffer b;
char buf2[1025];
int n=0;
this->recv_bytes=0;

do{
    //Anweisungen
 
    n=recv(this->c,buf2,1024,0);
    this->recv_bytes+=(n>=0)?n:0;
    buf2[n]='\0';

                        if(n>0 && this->recv_bytes>1024)
                        b.add(buf2,n);                              //FEHLER beim zweiten Aufruf
                        else if(n>0 && this->recv_bytes<=1024)
                        b.cpy(buf2,n);

    buf2[0]='\0';                     
    }while(/*Bedingung*/);
    //Anweisungen

So, das müsste an Source reichen, hoffe ich mal.

Gruß
cesupa
 
Hi.
Also gut, das gnaze geschieht in der Klasse Buffer, die ich geschrieben hab:

Code:
void buffer::add(const char* c2,long len)
{  
          this->buf2=new char[this->lenb];                  //Speicher reservieren mit der Größe des Puffers (vergrößert sich jedesmal: 1024 -> 3072 -> usw.) = FEHLER
     this->lenb2=this->lenb;        
     mcpy(this->buf2,this->buf,0,this->lenb);                  //Kopie von Puffer machen
    
 this->lenb2+=len;                                          //neue Puffer Größe
     this->buf=new char[this->lenb2];                           //Puffer mit neuer Größe generieren
      mcpy(this->buf,this->buf2,0,this->lenb);                   //Puffer-Kopie in Puffer kopieren
     mcpy(this->buf,c2,this->lenb,this->lenb2);                 //String in neuen Puffer dazukopieren
     
     this->lenb+=this->lenb2;                                                        
     this->lenb2=0;     
     delete[] this->buf2;                                
   
 }
Also in der Funktion hast du schonmal ein Memory-Leak drin. Dann kopierst du unnötig den Inhalt der Buffer umher. Warum ist eigentlich buf2 ein Klassenattribut?

C++:
void buffer::add(const char* c2,long len)
{
  char* tmpbuf = this->buf;

  this->buf = new char[this->lenb + len];

  mcpy(this->buf, tmpbuf, 0, this->lenb);
  this->lenb += len;

  delete[] tmpbuf;
}

Code:
void buffer::mcpy(char* c1,const char* c2,long start,long size)
{
     long z=0;
     for(start;start<=size;start++)
     {
     c1[start]=c2[z];
     z++;
     }
 }
Das soll vermutlich for (; start < size; start++) { heißen, oder?!

Gruß
 
Hab das ganze jetzt nochmal verbessert. Jetzt kopiert er die Daten ein paar mal mehr in den Puffer. Aber wenn ein neuer Puffer mit der Größe 7168 Bytes angelegt werden soll, erhalte ich von Windows wieder diese Fehlermeldung und gleich danach noch eine vom gleichen Typ:confused: . Wieso streikt das ganze an dieser Stelle?

Gruß
cesupa
 
Hi.

An welcher Stelle kommt denn der Fehler?

Hast du mal mit dem Debugger nachgeschaut welche Werte die einzelnen Variablen haben?

Versuch doch einfach mal ein minimales, kompilierbares Beispiel zu posten.

Gruß
 
Hab das ganze jetzt nochmal an einem anderen kürzeren Beispiel gemacht, da kommt der gleiche Fehler (jedoch nur einmal).

Hauptprogramm:

Code:
#include <cstdlib>
#include <iostream>
#include "buffer.h"

using namespace std;

int main(int argc, char *argv[])
{
    buffer b;
    char c1[]="Das ist ein Test!";  //17 Zeichen
    char c2[]=" Das ist der zweite Test.";      //25 Zeichen      
    char *c3;
    int len=0;
    
    b.cpy(c1,17);
    for(int i=0;i<50;i++)
    b.add(c2,25);
    len=b.get_size();
    c3=new char[len];
    
    b.get_buf(c3);
    for(int i=0;i<len;i++)
    cout<<i<<": "<<c3[i]<<endl;
    
    delete[] c3;
    system("PAUSE");
    return EXIT_SUCCESS;
}

Klasse buffer.h:

Code:
#include <iostream>
#include <cstdlib>
using namespace std;

class buffer
{
      public:
             buffer();
             ~buffer();
             void cpy(const char* c1,long size);
             void add(const char* c2,long len);
             int get_size();
             void get_buf(char* b);
             
      private:
              char* buf;
              unsigned long lenb,lenb2;
              void mcpy(char* c1,const char* c2,long start,long size);
      };

buffer.cpp:

Code:
#include "buffer.h"

buffer::buffer()
{         
                }
                
buffer::~buffer()
{
                 delete[] this->buf;
                 }
                 
void buffer::cpy(const char* c1,long size)
{
              this->buf=new char[size];
              this->lenb=size;
              mcpy(this->buf,c1,0,size);                       
}

void buffer::add(const char* c2,long len)
{
     char* tmpbuf=this->buf; 
     cout<<"tmpbuf angelegt."<<endl;            
     cout<<this->lenb<<" + "<<len<<" = "<<this->lenb+len<<endl;                      
     this->buf=new char[this->lenb+len];
     cout<<"Neuer Puffer wurde angelegt."<<endl;
     mcpy(this->buf,tmpbuf,0,this->lenb);
     cout<<"tmpbuf kopiert."<<endl;
     mcpy(this->buf,c2,this->lenb,this->lenb+len);
     cout<<"c2 addiert."<<endl;
     this->lenb+=len;
     delete[] tmpbuf;
 }

int buffer::get_size()
{
    return this->lenb;
}

void buffer::get_buf(char* b)
{
     mcpy(b,this->buf,0,this->lenb);
 }

//Private:

void buffer::mcpy(char* c1,const char* c2,long start,long size)
{
     long z=0;
     for(;start<=size;start++)
     {
     c1[start]=c2[z];
     z++;
     }
 }

So, wenn ich also add() 49mal durchlaufen lassen will, kommt schon nach den ersten paar Durchlüfen der Windowsfehler.

Gruß
cesupa
 
Zurück