winsock ( getaddrinfo ) : access violation error
-
ich versuche gerade die adresse eines hosts durch dessen Namen zu ermitteln. auch wenns nicht so viel sinn macht wollte ich mir, bei erfolg der funktion getaddrinfo, trotzdem nochmal den namen des hosts ausgeben lassen, allerdings tritt dabei immer eine accesviolationexception auf. hier mal der code:
#include <winsock2.h> #include <ws2tcpip.h> addrinfo* hostinfo(const char* hostname, const char* servname="http", const addrinfo* hints=0) { int ret; addrinfo* res=0; if(hints==0) { addrinfo aiHints; memset(&aiHints, 0, sizeof(aiHints)); aiHints.ai_family=AF_INET; aiHints.ai_socktype=SOCK_STREAM; aiHints.ai_protocol=IPPROTO_TCP; aiHints.ai_flags=AI_CANONNAME; ret=getaddrinfo(hostname, servname, &aiHints, &res); } else { ret=getaddrinfo(hostname, servname, hints, &res); } if(ret!=0) return 0; else return res; } int main() { addrinfo* res=0; addrinfo* ptr=0; int ret; WSADATA wsa; ret=WSAStartup(MAKEWORD(2,0), &wsa); if(ret!=0) return 1; res=hostinfo("www.google.de",80); if(res==0) return 2; for(ptr=res; ptr; ptr=ptr->ai_next) std::cout<<ptr->ai_canonname<<std::endl; freeaddrinfo(res); WSACleanup(); std::cin.ignore(2,'\n'); return 0; }der fehler tritt bei der ausgabe in der schleife aufm weiss aber nicht warum. ausserdem würd mich noch interessieren: gibts ne standardfunktion die dasselbe macht wie itoa, dann könnte ich nämlich den port/service als integer übergeben lassen.
-
Erstmal übergibst du der Funktion hostinfo einen int-Wert, wo sie einen char* erwartet (daß das durch den Compiler kommt, ist erstaunlich).
Zweitens solltest du dir die original zurückgegebene addrinfo* aufheben, damit du den richtigen Wert wieder freigeben kannst (Stichwort "Speicherleck").
Und drittens @itoa() - wirf mal einen Blick in die FAQ unter "Einmal zahl und zurück".
-
CStoll schrieb:
Erstmal übergibst du der Funktion hostinfo einen int-Wert, wo sie einen char* erwartet (daß das durch den Compiler kommt, ist erstaunlich).
Ups, ich hatte eine Version die const char* als 2. parameter erwartet unt eine mit int(und dann itoa verwendet; habs wohl beim posten übersehn zu korrigieren)
CStoll schrieb:
Zweitens solltest du dir die original zurückgegebene addrinfo* aufheben, damit du den richtigen Wert wieder freigeben kannst (Stichwort "Speicherleck").
zeigt der zeiger der zurückgegeben wird nicht auf den gleichen speicherbereich wie der, in der die liste von getaddrinfo nachher steht? oder wie sollte ichs sonst machen? addrinfo** zurückgeben?
CStoll schrieb:
Und drittens @itoa() - wirf mal einen Blick in die FAQ unter "Einmal zahl und zurück".
ok vielen dank, wird da gut erklärt

-
rudi_07 schrieb:
CStoll schrieb:
Zweitens solltest du dir die original zurückgegebene addrinfo* aufheben, damit du den richtigen Wert wieder freigeben kannst (Stichwort "Speicherleck").
zeigt der zeiger der zurückgegeben wird nicht auf den gleichen speicherbereich wie der, in der die liste von getaddrinfo nachher steht? oder wie sollte ichs sonst machen? addrinfo** zurückgeben?
Nach dem Aufruf von hostadr() ja, nach der Ausgabe-Schleife nicht mehr. Deshalb brauchst du eine zusätzliche Variable, die du die Liste durchlaufen lassen kannst.
(ansonsten könnte es natürlich auch sein, daß du die falschen Parameter an getaddrinfor() übergeben hast - damit kenne ich mich nicht so aus)
-
aber ich hab doch die variable res, die die adresse speichert, und verwende zum durchlaufen ptr oder versteh ich da was falsch?
-
*Brille putzt* OK, du hast recht - dann ziehe ich meine Bemerkung zurück.
PS: Ich hab' mir doch mal die Manpage zu man: getaddrinfo angesehen:
If the AI_CANONNAME bit is set, a successful call to getaddrinfo() will return a NUL-terminated string containing the canonical name of the specified hostname in the ai_canonname element of the first addrinfo structure returned.
(Auf Deutsch: Der Name steht im ersten Element der Liste - in den übrigen Elementen steht vermutlich Müll (oder schlicht NULL).
-
@ CStoll: Vielen Dank, also ich werds so nochmal versuchen, ohne die schleife dann weil ich glaube vor der exception wurde noch kurz irgendein string ausgegeben und vermutlich war das nächste element nicht NULL, das element ai_canonname diese zeigers aber schon. das wurde ja nirgends abgefragt deshalb könnte ich mir vorstellen dass es daher kommt (kanns im moment leider nich prüfen).
-
jupp, klappt

einfach die entsprechende stelle im code ersetzen durch:for(ptr=res; ptr; ptr=ptr->ai_next) if(ptr->ai_canonname) std::cout<<ptr->ai_canonname<<std::endl;