Für eine grosse Webseite, welche ich als Privatprojekt am entwickeln
bin, brauche ich einen Server, welcher das HTTP und das Websocket
Protokoll unterstützt. Aufgrund grösserer Flexibilität habe ich mich
entschieden einen eigenen WebsocketServer in C++ zu programmieren.
Dieser funktioniert auch bereits teilweise, aber leider kommt es beim
aufrufen einer Seite manchmal zu einem Segmentation fault. Ich konnte
leider noch nicht herausfinden, was zu diesem Segmentation fault führt,
und hoffe hier auf Tipps, Hinweise, Kritik und/oder
Verbesserungsvorschläge.
Den Sourcecode gibt es hier:
http://87.102.188.235/WebsocketServer.zip
GDB hat mir folgendes verraten:
1
Program received signal SIGSEGV, Segmentation fault.
2
[Switching to Thread 0x7ffff6e92700 (LWP 5005)]
3
0x00000000004052d0 in client::ws_send(void*) ()
4
(gdb) backtrace
5
#0 0x00000000004052d0 in client::ws_send(void*) ()
6
#1 0x00000000004059a5 in task::solve(unsigned char*) ()
7
#2 0x0000000000402eca in c_worker::do_work() ()
8
#3 0x0000000000402ff2 in worker() ()
9
#4 0x00000000004026b0 in callThreadFunc(void*) ()
10
#5 0x00007ffff7bc7b50 in start_thread (arg=<optimized out>) at pthread_create.c:304
11
#6 0x00007ffff6f6f0ed in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
Und jetzt erwartest du dass sich jemand gratis den Kopf für dich
zerbricht und dein Programm auseinander nimmt um deinen Fehler zu
finden?
Das darfst du schön selber machen. Kompiliere & Linke mit "-g" um
bessere debug-Informationen zu erhalten. Schaue in GDB nach wo genau der
Fehler auftritt. Finde heraus was den Fehler verursacht. Verwende
"valgrind" um Speicherfehler zu finden ( Fehler die nicht sofort zum
Absturz führen ).
der code ist furchtbar!
Wenig C++ - viel C - viele mögliche fehler!
> str = (char*)realloc(str,s);> str[s-1]=0;
was ist wenn kein Speicher da ist?
> #include "c_worker.cpp"
wer macht denn so etwas?
auch sollte man wenn man schon C++ macht eine string lib benutzen. Dann
könnte man sich soetwas unlesbares sparen:
> for(a=str+s-1;a>=str &&(*a==' '||*a==0);a--);
Da ist überhaupt keine sinnvolle Struktur erkennbar.
Warum wird das ganze http Protokoll in Client.cpp zerlegt? Dafür
schreibt man sich eine http Klasse.
Auch für die Socket sollte man an anfang gleich eine Klasse oder eine
fertige C++ lib nutzten. So verliert man doch alle Vorteile der
Fehlerbehandlung von C++
die http Header sind ideal für eine std::map - aber hier wird wieder
manuell mit listen gearbeitet.
Mit diesen Code würde ich keine Webserver laufen lassen, hier ist es nur
eine Frage der Zeit bis jemand von außen mit einen Buffer Overflow das
System lahmlegt oder gleich übernimmt.
Ein fehler wird hier nicht so schnell jemand finden.
Ich tippse auf out-of-Memory - hab mindestens ein leak gefunden [0] das
gefixt werden will.
Und jetzt wieder zurück zur Glaskugel.
[0] spoiler: [1]
[1] c_worker::buff
g457 schrieb:> hab mindestens ein leak gefunden [0] das> gefixt werden will.
...
> [1] c_worker::buff
Das ist kein leak, weil:
a) c_worker::buff nur einmal, bei der Initialisierung speicher
reserviert
b) Immer benötigt wird
c) Das Programm nie beendet wird
Dann hoffen wir mal, dass auch in zukünftigen Versionen niemals später
Worker herausgenommen werden. Denn dann musst du dich ja daran erinnern
(mit Post-It am Monitor zB) den Speicher dann doch freizugeben.
Alternativ kann man natürlich auch sauberen Code schreiben der auch
später noch wiederverwendet/modifiziert werden kann:
1
#include<memory>
2
3
staticconstexprBUFF_MAX=1024;// #define ist gefährlich und unnötig, besser Konstanten verwenden
> Das ist kein leak, weil:
Doch, ist ein klassischer Leak.
> a) c_worker::buff nur einmal, bei der Initialisierung speicher reserviert
..jede Instanz von c_worker
> b) Immer benötigt wird
..maximal so lange wie die jeweilige Instanz von c_worker lebt.
> c) Das Programm nie beendet wird
Sowas gibts per se nicht.
Glaubs mir. Räum auf, sonst findest Du die anderen Leaks nie.
Core dump erstellen lassen und das post-mortem Dump analysieren, z.B.
mit Debugger.
Je nachdem, was für ein Fehler es ist, kann es kontraproduktiv sein, auf
Verdacht die Quelle an X Stellen zu ändern. Wenn die Fehlstelle nicht
dabei ist (wahrscheinlich) und die Änderungen den Bug lediglich
maskieren, grüßt spätestens in ein paar Wochen das Murmeltier...
Schau dir mal POCO http://pocoproject.org an! Hier findest Du schon
einige Bauteile, die Du gleich verwenden kannst.
WebSocket findest Du in der Doku unter Poco::Net WebSocket.