Wie erhalte ich einen Byte-Array zurück?

  • C++/CLI

Es gibt 23 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    C-Quellcode

    1. std::unique_ptr<​uint8_t> getMemoryBytes(HANDLE processHandle, LPCVOID address, SIZE_T size)
    2. {
    3. auto buffer = std::unique_ptr<uint8_t>(new uint8_t[size]);
    4. ReadProcessMemory(processHandle, address, buffer, size, NULL);
    5. return buffer;
    6. }

    Cpp macht nämlich dabei eine optimierung, sodass es ist wie wenn die variable auserhalb deklariert wird, deshalb sollte es ohne move gehen
    en.m.wikipedia.org/wiki/Copy_e…Return_value_optimization

    Smart pointer rufen am ende diesselbe delete funktion auf, wie wenn du es manuell machst.
    Smart pointer hat natürlich noch bisschen mem overhead aber ist sicherer^^
    Memory wird dabei natürlich nicht gelöscht, sondern einfach vom Betriebssystem als freier Speicher markiert und kann für anderes benutzt werden. Überschreiben von den Daten würde extra Zeit kosten, also bevor nicht eine andere Applikation (oder deine) denselben Speicher verwendet und dabei überschreibt wird dasselbe drinne stehen bleiben...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Vultrax schrieb:

    *((int*)buffer) ??


    Ok.
    Wenn T ein Typ ist, dann ist T* ist ein Pointer auf T.
    Wenn x ein Ausdruck eines Pointer-Typs ist, dann dereferenziert *x diesen Pointer. Das kann dann entweder als Ausdruck (DoIt(*x);) oder als Ziel einer Zuweisung (*x = GetIt();) verwendet werden.
    Wenn x ein Ausdruck ist, dann castet (T)x den Ausdruck zu T. Was dabei genau passiert, hängt davon ab, welchen Typ x hat und was T ist. Aber der relevante Teil ist:

    Niko Ortner schrieb:

    In C und C++ kannst Du dem Compiler sagen: "Ich hab hier einen Pointer. Du weißt, dass er auf einen char zeigt. Heißt ja auch char*. Aber vergiss das jetzt. Tu einfach so, als würde der Pointer auf einen float zeigen. Also als wäre es ein float*."
    Das hat keinen Einfluss auf den tatsächlichen Wert des Pointers zur Laufzeit. Es ist immer noch einfach nur eine Zahl, die angibt, wo sich das Teil, auf das gezeigt wird, im Speicher befindet.


    Jetzt sehen wir uns den zitierten Code an:
    buffer ist ein unsigned char *. Also ein Pointer auf ein unsigned char.
    int* bezeichnet einen Pointer auf einen int.
    (int*)buffer castet buffer zu einem Pointer auf einen int.
    *((int*)buffer) dereferenziert diesen Pointer. In meinem Code wird das als Ausdruck verwendet, also wird aus dem RAM, an der Adresse, die in buffer steht, ein int gelesen.
    Der Cast ist nötig, weil *buffer einen unsigned char ergeben würde, und keinen int.

    Oder um es menschlicher zu sagen: buffer zeigt irgendwo in den RAM. Du liest von dieser Adresse einen int aus.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    @Vultrax Der .NET-Datentype Byte[] ist doch auch nix anderes als ein Pointer auf ein Byte-Array, wie er bei unsafe verwendet wird.
    Einfach richtig casten und feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Nein ist es nicht. Das ist erst mal eine Referenz auf managed Memory und kann random hin und her geschoben werden, ein einfacher cast in C# funktioniert damit auch nicht, man muss erst den Memory-Bereich anfixen, damit er nicht verschoben wird und dann erst bekommst du einen pointer und die Adresse ist anders als das ReferenzHandle
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---