DllStructCreate mit align

    • Offizieller Beitrag

    Ich weiß nicht mehr weiter! :/

    Entweder bin ich zu blöd, das zu verstehen oder es handelt sich um einen Bug. Vielleicht könnt ihr mich aufklären.

    Wenn ich bei DllStructCreate ein "align 16" verwende, dann sollte die Struktur doch an einer Speicheradresse liegen, die durch 16 teilbar ist, oder nicht?

    Manchmal klappt das, manchmal aber auch nicht. Ein kleines Testscript:

    Dabei kommt manchmal sowas raus:

    Code
    @@ Debug(4) : $pStruct1 = 0x008E91F8
    @@ Debug(5) : Structsize = 29
    @@ Debug(9) : $eax = -8

    $eax müsste aber "0" sein, wenn es eine 16-Byte-Aligned-Adresse ist.

    Manchmal stimmt es aber auch:

    Code
    @@ Debug(4) : $pStruct1 = 0x00BEAC90
    @@ Debug(5) : Structsize = 29
    @@ Debug(9) : $eax = 0
  • richtig...:Face:

    Sollte so sein, ist aber ein Bug. Wird auch nicht mehr gefixt, habe ich schon vor Jahren gemeldet. Juckt mich nicht, habe ich mir eben eine eigene Funktion zum alignen geschrieben.

    Dllstructcreate hat sowieso einige haarsträubende "Eigenheiten" in den letzten AutoIt-Versionen verpasst bekommen, die in den früheren Versionen definitiv nicht so waren....

    Zitat von Zitat aus der Hilfe

    The alignment of an array is the same as the alignment of one of the elements of the array.
    The alignment of the beginning of a structure is the maximum alignment of any individual member.
    Each member within the structure is be placed at its proper alignment as defined in the previous table, which require implicit internal padding, depending on the previous member.
    Structure size is an integral multiple of its alignment, which requires padding after the last member.

    Und das auch noch unterschiedlich, ob 32- bzw. 64-Bit. Viel Spass!

    • Offizieller Beitrag

    Ich habe mir gerade nochmal die Hilfe mehrfach durchgelesen.

    Eigentlich steht da gar nichts von der Speicherausrichtung des Pointers auf die Struktur. Bezieht sich das "align" nur auf die Ausrichtung mehrerer Elemente innerhalb der Struktur?

    In dem Fall muss man ja den Speicher erst extern anfordern und dann per Pointer übergeben.

    Wenn ich den Speicher per "_MemVirtualAlloc" anfordere, dann bekomme ich immer Adressen, bei denen die letzten 4 Stellen Nullen sind. Ist das normal?

    Dann bräuchte man gar nicht 16 Byte mehr anfordern und den Pointer umrechnen.

  • Wenn ich den Speicher per "_MemVirtualAlloc" anfordere, dann bekomme ich immer Adressen, bei denen die letzten 4 Stellen Nullen sind. Ist das normal?

    Scheint Systembedingt so zu sein. Man könnte ja eine Funktion schreiben, die das überprüft und ggf. aligned...auch auf XP und Win7/8/ME und was es sonst noch so gibt. Ich habe ehrlich gesagt keine Lust mehr, mich mit den AutoIt-DEV-gemachten Unzulänglickeiten rumzuschlagen, ich schreibe einen Fix und wenn nach einigen Jahren dann rauskommen sollte, dass ich den aktuell nicht mehr brauche, dann ist das dann eben so. Aber bis dahin kann ich entspannt die Rückmeldungen zu den aufgelaufenen Problemen der neuen Versionen beobachten und meine bisherigen Programme (hoffentlich) weiterbenutzen.:/

  • Wenn ich den Speicher per "_MemVirtualAlloc" anfordere, dann bekomme ich immer Adressen, bei denen die letzten 4 Stellen Nullen sind. Ist das normal?

    Weil du bei jedem Aufruf von _MemVirtualAlloc als Parameter für $pAddress eine null angibst.

    • Offizieller Beitrag

    Nein, laut: https://msdn.microsoft.com/en-us/library/…7(v=vs.85).aspx kann man mit "_WinAPI_GetSystemInfo" genauere Informationen über den virtuellen Speicher des Systems bekommen.

    Die WinAPI-Funktion gibt bei mir als Array-Element 7 eine Adresse von 65536 (hex: 0x10000) aus und das bedeutet laut Hilfe: "The granularity for the starting address at which virtual memory can be allocated." Somit heißt das wohl, dass der angeforderte Speicher immer auf eine solche Adresse liegt.

    Womit meine bisherigen Versuche bestätigt werden, bei denen die Adresse immer auf 0x....0000 enden.

    Aber das heißt dann auch, dass ich mir, bei virtuellen Speicher, um die 16-Byte-Ausrichtung keine Gedanken machen muss, da der Speicher ja sogar auf 64k ausgerichtet ist.

  • Somit heißt das wohl, dass der angeforderte Speicher immer auf eine solche Adresse liegt.

    Die Frage ist jetzt nur, ob man sich darauf verlassen kann, dass dieses Verhalten bei jedem Hard- und Softwareprodukt so ist.

    Was wiederum die Frage aufwirft, wieso, wenn AutoIt die C(++) Funktion malloc aufruft (und somit über eine (die) Systemfunktion ( VirtualAlloc?!) Speicher reserviert) und diesen Pointer dann an DllStructCreate() übergibt, dann diese Speicheradresse nicht xxx-aligned ist?!

    Das lässt nur einen Schluß zu, nämlich dass der von DllStructCreate() reservierte Speicher (mit dazugehörigem Pointer) nur Teil einer Speicheranforderung ist, ggf. steht ein Header mit den gesamten Infos zur Struct usw. "vorne dran". Es wurde sicher NICHT "vergessen", diesen Pointer aligned anzupassen. Wie schon bereits von mir beschrieben, war in früheren AutoIt-Versionen der Inhalt der Structs definitiv anders als zur Zeit. Wenn ich da ein DWORD; BYTE; UINT haben wollte, dann hab ich auch 9 Bytes bekommen. Aktuell ist die Struct 12 Bytes lang, und der UINT hat das Offset 8!

    Inwieweit das Systemkonform ist, kann und will ich nicht beurteilen, klar ist jedenfalls, dass "gemischte" Structs immer wieder zu Stress bei DLL-Aufrufen führen. qed.

    //EDIT

    Im Endeffekt bleibt nur, auf DllStructCreate() zu verzichten und sich den Speicher per _MemVirtualAlloc zu reservieren.

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (4. Januar 2018 um 18:58)

    • Offizieller Beitrag

    Wenn ich da ein DWORD; BYTE; UINT haben wollte, dann hab ich auch 9 Bytes bekommen. Aktuell ist die Struct 12 Bytes lang, und der UINT hat das Offset 8!

    Ja, weil "align 8" der Standardwert ist:

    Zitat

    To use a different alignment prefix the structure with the align keyword. The default value for n is 8.

    Willst Du Deine 9 Bytes haben, dann musst Du explizit "align 1" angeben:

    AutoIt
    $tStruct = DllStructCreate('DWORD;BYTE;UINT')
    $iSize = DllStructGetSize($tStruct)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iSize = ' & $iSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    $tStruct = DllStructCreate('align 1;DWORD;BYTE;UINT')
    $iSize = DllStructGetSize($tStruct)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iSize = ' & $iSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
  • Willst Du Deine 9 Bytes haben, dann musst Du explizit "align 1" angeben:

    Ja, MIR ist das klar :o)

    Ich kann nur jedem raten, sich bei "gemischten Structs" und deren Übergabe an "fremde" DLLs tunlichst mit diesem Thema zu beschäftigen. Immerhin ist nicht jede DLL mit der "Standard" C++ #PRAGMA Pack() - Direktive kompiliert...und schon gar nicht weiß "jeder", nach welchem System dort in den Structs die Daten "gepackt" werden. Aber dafür haben ja die C(++)-ler die *.h-files. Auch die wollen durchforstet werden....

    OT:

    Und da fällt mir sofort wieder eine Anwendung ein^^

    Man könnte wunderbar Bytes in den ungenutzten Plätzen dieser Structs verstecken und innerhalb der DLL oder eines Programms auswerten. Was man damit alles anstellen könnte...und das alles ohne Buffer-Overflow, denn der Buffer wird ja garnicht overflowed. Ein Buffer-Entry sozusagen8|