Problem mit Speicherwerverwaltung

  • Themenstarter Themenstarter Matthias_Nordwig
  • Beginndatum Beginndatum
M

Matthias_Nordwig

Hallo,

ich programmiere zur Zeit einen Chat für die Arbeit. Da sich dort nicht die Möglichkeit eines Servers bietet, muss ich den Austausch der Verbindungsadressen über Textdateien über ein Netzlaufwerk regeln. Entsprechend umständlich sind de Chatroutinen.
Dazu möchte ich mehrere Objektinstanzen des TClientSocket erstellen, was auch schon ganz gut klappt. Nur wird der Speicher entweder überschrieben auf dem ich Sie erzeuge, oder es gibt eine Zugriffsverletzung bei der Ausführung bestimmter Aktionen, wenn erstere bereits aktiv sind.

Hier der relevante Code:

Das ist der Zeiger den ich im Header definiert habe:
Code:
TClientSocket *client;

Diese Prozedur soll das Objekt erstellen:

Code:
void __fastcall Tchat::create_client(String add_ip,String add_port)
{

   *(&client+client_counter) = new TClientSocket(Application);
   (*(&client+client_counter))->Port=StrToInt(add_port);
   (*(&client+client_counter))->Host=add_ip;
   (*(&client+client_counter))->Active=true;
   (*(&client+client_counter))->OnConnect=OnConnect;
   (*(&client+client_counter))->OnDisconnect=OnDisconnect;
   client_counter++;
}

Wenn ich folgendes aufrufe oder ein neues Objekt anderer Art mit eigenem Adresscounter erstelle, dann wird auf den Speicher des TClientObjekts zugegriffen.

Code:
  anmeldung->Hide();
  chat->Show();

Bisher habe ich dafür nur die Erklärung, das eventuell der Speicher nach dem Beenden der Erstellungsfunktion des Objektes wieder frei gegeben wird.
Also stellt sich für mich die Frage, wie ich den Speicher global reservieren kann. (Wichtig dabei ist mir allerdings, das die Anzahl der Sockets dynamisch bleibt)
Natürlich würden mich auch elegantere Lösungsvorschläge interessieren, da ich hier sehr C-lastig programmiere wie ich weiss.

Mit vielen Dank im Vorraus,

und freundlichen Grüßen

Matthias Nordwig
 
Matthias_Nordwig hat gesagt.:
Code:
  *(&client+client_counter) = new TClientSocket(Application);

Diese Zeilen sind fehlerhaft:
Erst holst du dir über den &-Operator die Addresse des Zeigers (also nicht die Position, an die der Zeiger verweist), dann greifst du auf Speicher irgendwo hinter der Zeiger-Variable zu.

Korrekterweise sollte client von Typ
Code:
TClientSocket** client;
sein und der Zugriff dann folgendermassen aussehen:
Code:
*(client+client_counter) = new TClientSocket(Application);
//bzw kurz
client[client_counter] = new TClientSocket(Application);

Für diesen Fall musst du aber dennoch immer Acht geben, dass du genügend Speicher reservierst, um alle Zeiger auf die TClientSockets zu speichern.

Also wäre es geschickter die Klasse std::vector zu benutzen, dann brauchst du dich darum nicht zu kümmern.
Code:
vector<TClientSocket*> clients;

clients.insert(clients.end(),new TClientSocket(Application));
 
Und wieder hat mir dein Tip weitergeholfen.
:)

Jetzt hab ich das mit den Vektoren auch fast verstanden, außer:
Warum kann ich den Vektor nicht im Header definieren, sondern muss Ihn in der cpp definieren?

MfG

Matthias
 
Falls der Vector im inneren einer Klasse ist, muss ich sagen: hm, keine Ahnung, da bin ich überfragt.
Vielleicht hast du <vector> nicht im Header included?

Ansonsten, probiers mal mit:
extern vector<TClientSocket*> clients;
im Header und in der cpp dann
vector<TClientSocket*> clients;
 
Das klappt auch nicht. Es wird halt bei der Definition immer "ungültige Strukturoperation" ausgegeben, was mir in diesem Zusammenhang unklar ist. Aber es funktioniert ja auch so. Ich will den Vektor sowieso nirgends anders nutzen als im "body".

Auf hjedenfall vielen Dank für die Hilfe.

MfG

Matthias ordwig
 
Zurück