Memset und Stringübergabe
-
Hi
Ich habe es abgändert auf:
memset(strbuf+sizeof(ip)+sizeof(tcp), 0,sizeof(*strbuf)-sizeof(ip)-sizeof(tcp)); //führt zum absturtz ip.checksum = csum(strbuf, sizeof(ip)+sizeof(tcp)); memcpy(strbuf, &ip, sizeof(ip)); iErr = sendto(fd, strbuf, sizeof(*strbuf), 0,(struct sockaddr*)&to, sizeof(to));Trotzdem erhalte ich noch die beiden Fehlermeldungen!

Lg joe
-
strlen nicht sizeof, denn wie schon "niemand" erwähnt ergibt sizeof(*) == 4 (ausser 64bit plattform)
-
strlen wird nicht funktionieren, da er binäre Daten in sein char* kopiert.
Wenn buflen die Größe des übergebenen und reservierten Buffers sein soll, dann müsste sizeof in dem memset durch buflen ersetzt werden.Warum kopierst Du die ip Struktur ein zweites Mal (nach dem csum Aufruf)?
Im sendTo sollte eigentlich sizeof(ip)+sizeof(tcp) reichen (statt sizeof(strbuf)), da danach ja eh nur 0 im Speicher stehen.
-
Auch das führt zu den selben Fehlermeldungen. Wenn ich aber in der Funktion den String deklariere: char strbuf[60] = {0}; dann funktioniert der Code!
-
Könnte es sein, dass Du auf der VB Seite nicht genügend Speicher reserviert hast?
char buf[60]; std::cout << sizeof( buf) << "\n"; // == 60 ! char* buf2; std::cout << sizeof( buf2) << "\n"; // == 4 !Deswegen wird es funktionieren.
Bei der Übergabe eines Arrays mittels eines Zeigers, kannst Du innerhalb Deiner Funktion die Größe des reservierten Speichers i.A. nicht ermitteln. Du musst auf einen zusätzlichen Parameter, der die Größe angibt, ausweichen. Du bekommst die Größe übergeben.
Ausserdem muss sizeof(ip) + sizeof( tcp) > buflen sein, ansonsten gibt es auch einen Seg.Fault.Mal eine Frage am Rande: Benötigst Du die Daten, die Du per sendTo verschickst überhaupt in VB? Ansonsten reservier den Speicher innerhalb Deiner Funktion.
-
strbuf übergebe ich per VB: Private Declare Function sendpacket Lib "b.dll" (ByVal destIP As String, ByVal destPort As Integer, ByVal srcIP As String, _
ByVal srcPort As Integer, ByVal tcpFlag As Integer, Buf As String, ByVal Buflen As Integer) As Integerbuffer = Space(60)
result = sendpacket("192.168.2.1", 24, "192.168.2.1", 1024, 2, buffer, 60)Hmm habe noch folgendes ausprobiert:
char * buf = new char[buflen];
strcpy(buf,strbuf);Doch auch das funktioniert nicht!
LG
-
Meine VB Zeit liegt etwas zurück, aber String geht meines Wissen nicht. Zumindest in Access war das immer ein WideString. Was willst Du denn mit dem Buffer anschliessend in VB anfangen?
Was kommt bei dem strcpy für eine Fehlermeldung?
Was soll denn in dem strbuf drinstehen? In Deiner Routine benutzt Du den als reinen Output-Parameter?
Wenn Du binäre Daten in einen char* packst, dann kannst Du die strXYZ Routinen vergessen. Die brechen bei einem 0 Zeichen ab.
Z.B.... ip.offset = 0; ... memcpy(strbuf, &ip, sizeof(ip))führt dazu, dass in strbuf irgendwo mitten drin ein 0 Zeichen steht. strlen, strcpy usw. brechen dort ab. Deswegen benutzt ja auch korrekterweise memcpy.
Hast Du überprüft, ob 60 Zeichen reichen?
-
Fehlermeldungen: Die selben wie ich vorher gepostet habe.
Ich möchte einfach verschiedene Strings mitsenden können (Im Data Buffer des TCP Header). Diese werden vom Benützer in der Vb Form eingeben und dann der Dll übergeben.
60 Zeichen reichen, zudem habe ich es auch mit 1024 getestet und die selben zwei Fehler erscheinen. Ich hab auch buffer in Vb mit Buchstaben anstatt Nullen gefüllt, selber Effekt.
lG
-
Ok, wenn ich das richtig verstanden habe, soll der gesamte Buffer der aus VB übergeben wird, übertragen werden.
Dann darfst Du nicht in diesen kopieren, sondern solltest Dir einen neuen Buffer erzeugen und dort reinkopieren:
const int lenTotal = sizeof(sizeof(ip)+sizeof(tcp) + buflen char* b = new char[lenTotal]; memcpy(b, &ip, sizeof(ip)); memcpy(b+sizeof(ip), &tcp, sizeof(tcp)); memcpy(b+sizeof(ip)+sizeof(tcp), strbuf, buflen); iErr = sendto(fd, b, lenTotal, 0,(struct sockaddr*)&to, sizeof(to)); delete [] b;BTW, teste Deine Routine erstmal ohne DLL in einem kleinen C++-Programm. Wenn sie da funktioniert, liegt es an dem VB Aufruf.
-
Mein Code sieht nun folgendermassen aus:
const int lenTotal = sizeof(ip)+sizeof(tcp)+ buflen; char* b = new char[lenTotal]; forcsum.srcaddr = inet_addr(srcIP); memcpy(b, &forcsum, sizeof(forcsum)); memcpy(b+sizeof(forcsum), &tcp, sizeof(tcp)); tcp.checksum = csum(b, sizeof(forcsum)+sizeof(tcp)); //hier wird automatisch &b[0] übergeben memcpy(b, &ip, sizeof(ip)); memcpy(b+sizeof(ip), &tcp, sizeof(tcp)); memcpy(b+sizeof(ip)+sizeof(tcp), strbuf, buflen); ip.checksum = csum(b, sizeof(ip)+sizeof(tcp)); iErr = sendto(fd, b, lenTotal, 0,(struct sockaddr*)&to, sizeof(to));Das funktioniert wunderbar. Ich habe jedoch noch einige Verständigungsfragen:
sizeof(ip)+sizeof(tcp)+ buflen; buflen ist die Grösse des Strings in Anzahl Zeichenelementen, sizeof die Grösse von IP und TCP in Byte, wie funktioniert diese Addition oder sind das Zeiger? müsste man buflen nicht auch in Bytegrösse sizeof(buflen) angeben?
memcpy(b+sizeof(ip), &tcp, sizeof(tcp)); wie funktionieren hier die Zeiger (b+sizeof) ?
Für was hat es den bei meinem alten code memset überhaupt benötigt?
Lg Joe
-
Achja nochwas! Wie könnte ich den eine Funktion einbauen die ein Error in der Dll abfangt und auswertet, fals ein Fehler entsteht?
-
Ich bin jetzt davon ausgegangen, dass buflen die Größe in Byte ist. Wenn Du mit 2Byte Characters hast und nur die Zeichenanzahl übergibst, dann musst Du die natürlich mit 2 multiplizieren.
[JoE] schrieb:
sizeof(ip)+sizeof(tcp)+ buflen; buflen ist die Grösse des Strings in Anzahl Zeichenelementen, sizeof die Grösse von IP und TCP in Byte, wie funktioniert diese Addition oder sind das Zeiger?
b ist ein Zeiger auf einen Speicherbereich.
Dein Speicher soll nach Deiner Kopierei so aussehn:
IP-Header<x Bytes> | TCP-Header<y Bytes> | Userdaten<buflen Bytes>
x ist sizeof( ip)
y ist sizeof( tcp)
und der Rest sind die Userdaten.
Beispiel: sizeof(ip) = 20 Bytes, sizeof(tcp) = 30 Bytes, buflen = 60 Bytes, dann muss Dein Speicher, den Du reservierst also 20+30+60=110 Bytes gross sein.memcpy(b+sizeof(ip), &tcp, sizeof(tcp)); wie funktionieren hier die Zeiger (b+sizeof) ?
b ist ein Zeiger auf den ersten Speicherplatz. Die Struktur tcp soll hinter die Struktur ip kopiert werden. Also musst Du die Daten nicht an den ersten Speicherplatz kopieren, sondern ausrechnen wo die Struktur ip endet. Das ist dann der erste plus sizeof(ip). Und das steht da.
Für was hat es den bei meinem alten code memset überhaupt benötigt?
Keine Ahnung, das machte keinen Sinn zumindest unter der Annahme, dass der VB-User Daten, die einen Header gepackt werden sollen, verschicken kann.
BTW, Du solltest Dir mal Zeiger in C genauer anschauen, wenn Du häufiger mit solchem Code arbeiten musst.
Achja nochwas! Wie könnte ich den eine Funktion einbauen die ein Error in der Dll abfangt und auswertet, fals ein Fehler entsteht?
Was meinst Du damit? Soll der VB User keine Rückmeldung mehr bekommen?
-
Em erstmal vielen Dank für deine Antworten / Erklärungen. Ich werde mich noch mehr mit Zeiger auseinandersetzen. Gibts dazu ein sinvolles Tutorial?
Em, mit dem Error abfangen mein ich das so: Entsteht in der Dll ein Fehler, dann soll der VB Prozess nicht abstürzen, sondern dem Benutzer einen genau Error Meldung zeigen. Dazu müsste man in der Dll eine Fehlerbehandlungsroutine einbauen die auswerten kann, was für ein Fehler entsteht und diesen dann ignoriert (like Vbs On Error Resume next).
Ich kann ja ein entsprechender Integer Wert der Funktion Rawsocket zurückgeben und diesen dann in Vb auswerten.