WinApi Funktion in C++ "aendern"
-
Benutz doch in solchen Beispielen konsequent die Smartpointer. So wie jetzt ist es doch bloß C mit new statt malloc und der Threadersteller fragt sich, wo überhaupt der Unterschied zwischen den Sprachen ist.
-
Ja, Sire! Sofort Sire!
unique_ptr<IP_ADAPTER_ADDRESSES> get_adapters_addresses(ULONG family, ULONG flags) { using ptr_t = std::unique_ptr<IP_ADAPTER_ADDRESSES>; ULONG size = 15*1024; // lt. doku auto addr = ptr_t{(PIP_ADAPTER_ADDRESSES)new char[size]}; ULONG rc; while((rc=GetAdapterAddresses(family, flags, nullptr, addr.get(), &size))==ERROR_BUFFER_OVERFLOW) addr=ptr_t{(PIP_ADAPTER_ADDRESSES)new char[size]}; if(rc==ERROR_SUCCESS) return addr; // Hier koennte Ihre Fehlerbehandlung stehen... switch(rc){ case ERROR_NOT_ENOUGH_MEMORY: throw bad_alloc{}; // .... default: throw runtime_error{"What the zuny!?"}; } }
@c_to_cpp: wie Du siehst sind nach SeppJs Einwand und einer weiteren Iteration des Codes alle händischen Speicherfreigaben verschwunden. Der Code ist kürzer und klarer.
-
@c_to_cpp
Arbeite erstmal mit malloc/free, ist für den Anfang das einfachste.@Furble Wurble
Darf man denn überhaupt ein mitnew char[]
besorgtes char-Array mitdelete (POD_TYPE*)addressOfFirstElement
freigeben?
Wenn nicht, was ich vermute, dann bekommt man mitunique_ptr<POD_TYPE>
ein bisschen ein UB Problem.
Ich hab' das bisher immer mitmalloc
+shared_ptr<POD_TYPE>
+ custom deleter derfree
aufruft gemacht.(Man kann natürlich auch nen
unique_ptr<POD_TYPE, CLibFreeDeleter>
o.ä. verwenden. Wenn man vorwiegendauto
verwendet ist das OK, aber sonst... bäh.)ps.: So:
#include <memory> #include <cassert> template <class T> std::shared_ptr<T> AllocateSizedPod(size_t size) { assert(size >= sizeof(T)); std::shared_ptr<T> const ptr(static_cast<T*>(std::calloc(1, size)), std::free); if (!ptr) throw std::bad_alloc(); return ptr; }
-
hustbaer schrieb:
@Furble Wurble
Darf man denn überhaupt ....Nein. Das ist mir auch aufgefallen - sonst würde ich auch schon pofen.
Tatsächlich stimme ich Dir zu malloc/free ist einfacher korrekt hinzubekommen, als new/delete.
Ich bastel gerade noch an einem wrapper, aber der nimmt einen vector<char> als Speicher...ist aber nur für mich, damit ich gleich schlafen kann. Ohne schlechtes Gewissen...
-
Nimm new und delete, das macht es noch leichter!
~ Furble WurbleIch <- doof!
Mal eben so aus dem Lamäng einen Code hinpfuschen...Nie wieder!
-
Danke erstmal. Der Wrapper von Furble wäre evtl. noch interessant... ?
Ich werde es erstmal bei malloc / free belassen. Habe noch 2 Fragen :- Wenn ich das ganze mit den Smart_Pointern usw. weglasse (Habe mich damit noch zuwenig befasst) müsste folgender Code aber gehen oder ?
PIP_ADAPTER_ADDRESSES addr = (PIP_ADAPTER_ADDRESSES)new char[size]; while((rc=GetAdapterAddresses(family, flags, nullptr, addr, &size)==ERROR_BUFFER_OVERFLOW){ delete[]addr; addr=(PIP_ADAPTER_ADDRESSES)new char[size]; }
Hier müsste ja wie im Original code nach dem 1. Aufruf (wenn dieser denn Failt) die "neue" Speichergroesse angefordert werden. Kann es hier ein Problem geben ? Ich weiß nicht ob GetAdapterAdresses addr evtl. ändert, ich würde den dann noch wegspeichern davor , damit delete wieder den Originalpointer erhält?
2.)
auf der MSDN Seite ( Google: site:msdn.microsoft.com https://msdn.microsoft.com/de-de/library/windows/desktop/aa366314%28v=vs.85%29.aspx )wird der Speicher so freigegeben ... ??? :
//6.Free any memory allocated for the pAdapterInfo structure.
if (pAdapterInfo) free(pAdapterInfo);
==>> pAdapterInfo ist doch eigentlich ne Linked-List, ist das Speicherfreigeben so nicht falsch ? Der gibt doch nur für ein Element frei ? ? ?
-
c_to_cpp schrieb:
Ich weiß nicht ob GetAdapterAdresses addr evtl. ändert, ich würde den dann noch wegspeichern davor, damit delete wieder den Originalpointer erhält?
GetAdaptersAddresses()
kann den Wert (die Adresse auf die der Zeiger zeigt) des ParametersAdapterAddresses
nicht ändern, da er per value übergeben wird.c_to_cpp schrieb:
==>> pAdapterInfo ist doch eigentlich ne Linked-List, ist das Speicherfreigeben so nicht falsch ? Der gibt doch nur für ein Element frei ? ? ?
Das
delete[]
gibt allen Speicher frei, den du mitnew T[N]
angefordert hast.IP_ADAPTER_ADDRESSES
ist zwar eine linked list, "lebt" aber nur in dem von dir bereitgestelltem Speicher. Eine Liste ist es deshalb, weil die einzelnenIP_ADAPTER_ADDRESSES
unterschiedlich groß sein können. Du hättest sonst keine Möglichkeit festzustellen, wo einIP_ADAPTER_ADDRESSES
endet und ein neues anfängt.
-
Wenn man die
PIP_ADAPTER_ADDRESSES
nur lokal braucht kann man das auch ganz ohne Pointer per std::vector<char> lösen (ohne Sicherheitsgurte und Helm):#include <vector> void f() { ULONG RequiredSize = 0; ::GetAdaptersAddresses( AF_INET, 0, NULL, NULL, &RequiredSize ); if( RequiredSize > 0 ) { std::vector<char> Buffer( RequiredSize ); PIP_ADAPTER_ADDRESSES Addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>( &Buffer[0] ); ::GetAdaptersAddresses( AF_INET, 0, NULL, Addresses, RequiredSize ); } }
-
GetAdaptersAddresses() kann den Wert (die Adresse auf die der Zeiger zeigt) des Parameters AdapterAddresses nicht ändern, da er per value übergeben wird.
Stimmt, peinlich.
Ok, dann müsste das mit meinen paar Zeilen eigentlich funktionieren...
-
c_to_cpp schrieb:
GetAdaptersAddresses() kann den Wert (die Adresse auf die der Zeiger zeigt) des Parameters AdapterAddresses nicht ändern, da er per value übergeben wird.
Stimmt, peinlich.
Ok, dann müsste das mit meinen paar Zeilen eigentlich funktionieren...Bloß, dass man dann eben im Falle einer Exception ein Problem hat.
-
c_to_cpp schrieb:
Danke erstmal. Der Wrapper von Furble wäre evtl. noch interessant... ?
Na klar. Ich habe ja gerade eine richtige Serie von guten Ideen in diesem Thread
So habe ich mir das minimal gedacht:template<typename T> class wrapper : private vector<char> { using impl_t = vector<char>; public: using pointer = T; using impl_t::resize; wrapper() = default; wrapper(size_t sz) : impl_t(sz) { } pointer get() { return reinterpret_cast<pointer>(&(*this)[0]); } }; using pip_adapter_addresses = wrapper<PIP_ADAPTER_ADDRESSES>; pip_adapter_addresses get_adapters_addresses(ULONG family, ULONG flags) { ULONG size = 15*1024; // lt. doku pip_adapter_addresses addr(size); ULONG rc; while((rc=GetAdaptersAddresses(family, flags, nullptr, addr.get(), &size))==ERROR_BUFFER_OVERFLOW) addr.resize(size); if(rc==ERROR_SUCCESS) return addr; // Hier koennte Ihre Fehlerbehandlung stehen... switch(rc){ case ERROR_NOT_ENOUGH_MEMORY: throw bad_alloc{}; // .... default: throw runtime_error{"What the zuny!?"}; } }
-
DocShoe schrieb:
[...]
yay!