Mit Wert aus void* rechnen



  • Hallo, ich hab eine Funktion die mir einen Wert zurück gibt. Also so was:

    void *var= Funktion();
    
    Jetzt möchte ich folgendes machen:
    Der Wert der in var steht zu dem möchte ich jetzt gerne eine bestimmte Zahl hinzu addieren. Aber ich weiß nicht wie ich var konvertieren muss.
    
    int erg = var; Dabei meckert der Compiler ( Konvertierung von void* nach int nicht möglich). Irgendwelche Ideen?
    

  • Mod

    Was meinst du denn mit dem "Wert", den die Funktion zurück gibt? Möchtest du mit dem Zeiger selber rechnen? Dann musst du dem Compiler erst sagen, welche Form von Pointerarithmetik du wünscht, da für void* keine Arithmetik erlaubt ist. Also caste den Zeiger in den gewünschten Zeigertyp um und rechne dann mit diesem.

    Oder meinst du, dass der Zeiger auf irgendeine Art von Wert zeigt und mit diesem möchtest du weiter rechnen? Auch dann musst du erst einmal auf den passenden Zeigertyp umcasten, denn void ist kein gültiger Typ. Und im Gegensatz zum ersten Absatz musst du dann eben erst dereferenzieren, bevor du weiter rechnest.

    Wieso gibt dir deine Funktion überhaupt einen void* zurück? Das ist unüblich in C++. Allgemein die Warnung, dass Gefrickel mit Zeigern, wenn man sich nicht auskennt (was offenbar bei dir der Fall ist), zu fast 100% schief geht. Mit den üblichen C++-Mitteln wärst du vermutlich besser bedient.



  • Hab es hin bekommen mit einem: int erg = int(var);
    Aber das wäre ja C-Style wieso geht hier kein static_cast<int>(var); ?

    [BCC32 Fehler] main.cpp(60): E2031 Typumwandlung von 'void *' nach 'int' nicht zulässig

    Sagt er beim static_cast



  • SeppJ schrieb:

    Was meinst du denn mit dem "Wert", den die Funktion zurück gibt? Möchtest du mit dem Zeiger selber rechnen? Dann musst du dem Compiler erst sagen, welche Form von Pointerarithmetik du wünscht, da für void* keine Arithmetik erlaubt ist. Also caste den Zeiger in den gewünschten Zeigertyp um und rechne dann mit diesem.

    Oder meinst du, dass der Zeiger auf irgendeine Art von Wert zeigt und mit diesem möchtest du weiter rechnen? Auch dann musst du erst einmal auf den passenden Zeigertyp umcasten, denn void ist kein gültiger Typ. Und im Gegensatz zum ersten Absatz musst du dann eben erst dereferenzieren, bevor du weiter rechnest.

    Wieso gibt dir deine Funktion überhaupt einen void* zurück? Das ist unüblich in C++. Allgemein die Warnung, dass Gefrickel mit Zeigern, wenn man sich nicht auskennt (was offenbar bei dir der Fall ist), zu fast 100% schief geht. Mit den üblichen C++-Mitteln wärst du vermutlich besser bedient.

    void *var= Funktion(); 
    
    var enthält jetzt den Wert 10 jetzt möchte ich dazu z.b. den Wert 5 rechnen.
    So das ich mir am Ende den Wert 15 ausgeben lassen kann und er soll in einem int stehen.
    
    Meine eigentliche Funktion ist eine WIN API Funktion die diesen void* Zeiger zurückgibt daher kann ich da jetzt nix ändern. :-(
    

  • Mod

    void** schrieb:

    Hab es hin bekommen mit einem: int erg = int(var);
    Aber das wäre ja C-Style wieso geht hier kein static_cast<int>(var); ?

    [BCC32 Fehler] main.cpp(60): E2031 Typumwandlung von 'void *' nach 'int' nicht zulässig

    Sagt er beim static_cast

    Der Compiler ist schlauer als du. static_cast ist für "korrekte" Umwandlungen, deren Richtigkeit überprüft werden kann. Und das dies niemals nicht eine korrekte Umwandlung ist, beschwert sich der Compiler. Der C-Cast hingegen ist die Holzhammermethode, mit der du dem Compiler sagst "Halt die Fresse, ich hab Recht!". Dummerweise sieht es so aus, als hättest nicht du Recht, sondern doch der Compiler.

    Programmieren ist nicht Raten! Du musst von jedem einzelnen Zeichen in deinem Code genau wissen, wo und warum du es setzt. Du kannst durch zufälliges Einfügen von genügend Sonderzeichen und Casts den größten Schwachsinn zum Compilieren bringen. Funktionieren wird das Programm dann freilich nicht, denn Müll bleibt Müll, selbst wenn man dem Compiler vormacht, dass es ein Meisterwerk wäre. Der Compiler ist nicht dein Feind, den du bekämpfen musst, sondern dein Freund, der dich auf deine Fehler hinweist.

    void** schrieb:

    var enthält jetzt den Wert 10 jetzt möchte ich dazu z.b. den Wert 5 rechnen.
    So das ich mir am Ende den Wert 15 ausgeben lassen kann und er soll in einem int stehen.

    Meine eigentliche Funktion ist eine WIN API Funktion die diesen void* Zeiger zurückgibt daher kann ich da jetzt nix ändern. 😞

    Glaub ich dir nicht. Beziehungsweise ich glaub dir wohl, dass du selber glaubst, was du hier behauptest. Aber alles was du zeigst und sagst deutet darauf hin, dass du in Wirklichkeit keine Ahnung hast, was hier vorgeht oder was Zeiger überhaupt sind. Daher bin ich auch parteiisch für den Compiler. Nenn doch einfach mal die Winapi-Funktion, von der du hier sprichst beim Namen!



  • SeppJ schrieb:

    void** schrieb:

    Hab es hin bekommen mit einem: int erg = int(var);
    Aber das wäre ja C-Style wieso geht hier kein static_cast<int>(var); ?

    [BCC32 Fehler] main.cpp(60): E2031 Typumwandlung von 'void *' nach 'int' nicht zulässig

    Sagt er beim static_cast

    Der Compiler ist schlauer als du. static_cast ist für "korrekte" Umwandlungen, deren Richtigkeit überprüft werden kann. Und das dies niemals nicht eine korrekte Umwandlung ist, beschwert sich der Compiler. Der C-Cast hingegen ist die Holzhammermethode, mit der du dem Compiler sagst "Halt die Fresse, ich hab Recht!". Dummerweise sieht es so aus, als hättest nicht du Recht, sondern doch der Compiler.

    Programmieren ist nicht Raten! Du musst von jedem einzelnen Zeichen in deinem Code genau wissen, wo und warum du es setzt. Du kannst durch zufälliges Einfügen von genügend Sonderzeichen und Casts den größten Schwachsinn zum Compilieren bringen. Funktionieren wird das Programm dann freilich nicht, denn Müll bleibt Müll, selbst wenn man dem Compiler vormacht, dass es ein Meisterwerk wäre. Der Compiler ist nicht dein Feind, den du bekämpfen musst, sondern dein Freund, der dich auf deine Fehler hinweist.

    void** schrieb:

    var enthält jetzt den Wert 10 jetzt möchte ich dazu z.b. den Wert 5 rechnen.
    So das ich mir am Ende den Wert 15 ausgeben lassen kann und er soll in einem int stehen.

    Meine eigentliche Funktion ist eine WIN API Funktion die diesen void* Zeiger zurückgibt daher kann ich da jetzt nix ändern. 😞

    Glaub ich dir nicht. Beziehungsweise ich glaub dir wohl, dass du selber glaubst, was du hier behauptest. Aber alles was du zeigst und sagst deutet darauf hin, dass du in Wirklichkeit keine Ahnung hast, was hier vorgeht oder was Zeiger überhaupt sind. Daher bin ich auch parteiisch für den Compiler. Nenn doch einfach mal die Winapi-Funktion, von der du hier sprichst beim Namen!

    Ich muss zugeben ich habe mich schon längere Zeit nicht mehr mit C++ beschäftigt und bin etwas raus.

    Nochmal kurz zum auffrischen was bei einem Zeiger intern passiert.

    z.b.:

    #include <iostream>
    using namespace std;
    
    int main(int argc, char* argv[])
    {
    
    int var = 10;
    int *ptr = 0;
    
    ptr = &var;
    
    cout<<*ptr << "\n";
    
    system("PAUSE");
    }
    

    z.b.:
    var steht im speicher an Adresse: 18ff50 an dieser Adresse steht der Wert 10.

    ptr = &var;  // Hier sage ich jetzt ptr soll auf die Adresse von var zeigen
    

    int *ptr; steht an Adresse 18ff4c

    Also im Speicher sieht es doch dann so aus:

    18ff4c(Zeiger Adresse) 18ff50(Wert der an der Adresse von Zeiger steht)

    cout<<*ptr;  // *ptr zeigt jetzt auf den Inhalt der an Adresse 18ff4c steht. Der Inhalt ist ja in diesem Fall 18ff50 und jetzt zeigt *ptr was an Adresse 18ff50 steht und das ist in dem Fall der Wert 10
    

    Das sollte doch richtig sein. (Ich hoffe meine Erklärung war verständlich.^^)
    Falls ich was falsches geschrieben habe dann bitte verbessern. Bin hier ja auch schließlich um was zu lernen.

    Um die WIN API um die es hier geht ist: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx


  • Mod

    void** schrieb:

    Das sollte doch richtig sein. (Ich hoffe meine Erklärung war verständlich.^^)
    Falls ich was falsches geschrieben habe dann bitte verbessern. Bin hier ja auch schließlich um was zu lernen.

    Du bist inkonsistent was die Dereferenzierung angeht:

    // *ptr zeigt jetzt auf den Inhalt der an Adresse 18ff4c steht. Der Inhalt ist ja in diesem Fall 18ff50 und jetzt zeigt *ptr was an Adresse 18ff50 steht und das ist in dem Fall der Wert 10
    

    ptr ist was anderes als *ptr ! ptr ist ein Zeiger auf int , das bedeutet, *ptr ist ein int und zeigt dementsprechend auf gar nichts.

    Um die WIN API um die es hier geht ist: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx

    Also liegt der zweite Fall aus meiner ersten Antwort vor:

    SeppJ schrieb:

    Oder meinst du, dass der Zeiger auf irgendeine Art von Wert zeigt und mit diesem möchtest du weiter rechnen? Auch dann musst du erst einmal auf den passenden Zeigertyp umcasten, denn void ist kein gültiger Typ. Und im Gegensatz zum ersten Absatz musst du dann eben erst dereferenzieren, bevor du weiter rechnest.

    Du willst wirklich mit VirtualAlloc rumspielen, wenn du nicht einmal Pointer richtig kannst? Das ist eine sehr spezielle, sehr niedriglevelige Funktion. Was hast du vor? Intraprozesskommunikation? Da gibt es wesentlich bessere Mittel.



  • Ich sehe schon ich werfe da einige Begrifflichkeiten etwas durcheinander. Bzw. ich meine das richtige aber schreibe das falsche. Vielleicht sollte ich nochmal in mein Buch rein schauen um vergessenes aufzufrischen. 🙄 (Ich glaub da gibt es noch einiges nachzuholen für mich. 😮 )

    { Intraprozesskommunikation sagt mir nichts der Begriff. Beim Googeln bin ich hier drauf gestoßen: https://de.wikipedia.org/wiki/Interprozesskommunikation )

    Aber bevor ich auf andere Mittel greife würde ich gerne wissen ob es für mein gegebenes Problem eine Lösung gibt. Also ob möglich ist einen sauberen cast darauf an zu wenden.

    Du hast ja schon folgendes geschrieben:
    "static_cast ist für "korrekte" Umwandlungen, deren Richtigkeit überprüft werden kann. Und das dies niemals nicht eine korrekte Umwandlung ist, beschwert sich der Compiler."

    Jetzt stellt sich ja dann noch für mich die Frage gibt es überhaupt eine Möglichkeit das ganze ohne meine Holzhammermethode zu realisieren?


  • Mod

    void** schrieb:

    Jetzt stellt sich ja dann noch für mich die Frage gibt es überhaupt eine Möglichkeit das ganze ohne meine Holzhammermethode zu realisieren?

    Ja! Caste den void Zeiger in einen Zeiger auf den korrekten Typ.

    Aber bevor ich auf andere Mittel greife würde ich gerne wissen ob es für mein gegebenes Problem eine Lösung gibt.

    Erklär doch lieber dein eigentliches Problem. Wie ich schon schrieb, ist es schwer vorstellbar, dass du überhaupt VirtualAlloc brauchst. Du hast höchstwahrscheinlich einen völlig falschen Ansatz für dein eigentliches Problem.



  • Aber bevor ich auf andere Mittel greife würde ich gerne wissen ob es für mein gegebenes Problem eine Lösung gibt.

    Erklär doch lieber dein eigentliches Problem. Wie ich schon schrieb, ist es schwer vorstellbar, dass du überhaupt VirtualAlloc brauchst. Du hast höchstwahrscheinlich einen völlig falschen Ansatz für dein eigentliches Problem.[/quote]

    Also es gibt eine bestimmte Anwendung dort soll ein Wert aus einer bestimmten Speicheradresse gelesen werden. Die Base Adresse kann man nicht so leicht ermitteln dafür musste man die Anwendung erst reverse und das ist mir gerade zu aufwendig. Eine DLL lässt sich nicht in den Zielprozess injecten.
    Daher verwende ich eine Code Injection.

    Angenommen dort steht:

    0x12ff90 mov eax,ecx

    Jetzt muss ich wissen welchen Wert eax enthält. Also mache ich folgendes:
    - Ich reserviere Speicher in der Zielanwendung
    - Mit WriteProcessMemory schreibe ich an Adresse 0x12ff90 den JMP opcode (0xE9) der dann zum reservierten Speicher springt anschließend schreibe in den Wert von ecx in eine Speicheradresse vom eben reservierten Speicher. (Diese Adresse weiß ich ja und kann diese dann später bequem mit ReadProcessMemory auslesen.

    Anschließend stelle ich den mov eax,ecx Befehl wieder her und springe zurück an die passende Stelle im Code. Das funktioniert auch alles gut nur mit dem cast stand ich etwas auf dem Schlauch.

    Ich habe mich seit ca. 3-4 Jahren nicht mehr intensiv mit C++ beschäftigt bzw. es so gut wie gar nicht mehr gebraucht. Daher happert es jetzt teilweise an einigen Grundlagen. 😞 Aber da muss ich wohl durch.

    Ich hoffe ich konnte erklären was ich da vor habe. (Manchmal meine ich X aber schreiben Y 🤡 )


  • Mod

    Also kurz: Du möchtest einen Wert von einer Anwendung (die du geschrieben hast) zu einer anderen Anwendung (die du ebenfalls geschrieben hast) übertragen? Das ist die erwähnte Intraprozesskommunikation und das geht in der Regel wesentlich einfacher.

    Ansonsten: Hast du das andere nun hinbekommen?



  • Nein, die Zielanwendung ist nicht von mir. Und nein, ich bin noch nicht mit allem fertig ich hab am Wochenende nix weiter dran gemacht,


Anmelden zum Antworten