free: invalid conversion from "volatile void*" to "void*"



  • Hallo zusammen,

    Vorweg: Meine Frage ist etwas kurios, weil ich einen etwas seltsamen Compiler benutze.
    Ich programmiere in dieser Sache für einen atmegaAVR Controller. Der C++-Compiler ist irgendein alter vergewaltigter gcc, der einige C++ Sprachmittel kennt (z.B. Templates, Klassen), einige nicht (z.B. new / delete). Ich könnte einen reinen C Compiler verwenden, mag ich aber nicht, da sich in meinem Fall Templates und Objektorientierung als äußerst praktisch erweisen.

    Folgende Codeausschnitte sind relevant:

    template <typename sensor_type> struct PWMSensorArray
    {
       // ...
        volatile value_type * volatile values;
    };
    

    Die Daten und der Pointer "values" müssen volatile qualifiziert sein, da hier Werte von einem Interrupt reingeschrieben werden.

    Speicherreservierung sieht so aus:

    values = (volatile value_type * volatile)malloc(size * sizeof(value_type));
    

    Speicherfreigabe sieht so aus:

    free(values);
    

    Der Compiler haut mir das free(values); mit der folgenden Fehlermeldung um die Ohren:

    gls_pwmsensorarray.h(-1): In destructor 'PWMSensorArray<sensor_type>::~PWMSensorArray() [with sensor_type = TestSensor]':
    GLS_CO~1.CPP(8): instantiated from here
    gls_pwmsensorarray.h(64): error: invalid conversion from 'volatile void*' to 'void*'
    gls_pwmsensorarray.h(64): error: initializing argument 1 of 'void free(void*)'

    Abhilfe für die Meldung schafft folgender Cast:

    free((void*)values);
    values = NULL;
    

    Die Frage ist, ob das auch das Problem löst. Kann ich das so gefahrlos casten? Was passiert, wenn vor der Speicherfreigabe das "volatile" weggecastet wird? Wird dann die Freigabe des Speichers auch korrekt durchgeführt?

    /edit:
    In den meisten geplanten Fällen ist value_type int oder float.


  • Mod

    Ja, das kannst du machen. Du solltest dir aber natürlich sicher sein, dass das alles korrekt abläuft, wenn du solche Casts verwenden willst.

    Der Compiler versucht dich hier davor zu bewahren den volatile Speicherbereich freizugeben, da er annehmen muss, dass dieser noch durch irgendeine ihm unbekannte Quelle benutzt wird (genau das sagt das volatile ja aus). Wenn du dir sicher bist, dass dies nicht der Fall ist, kannst du ihn auch freigeben.

    P.S.: Klingt wirklich extrem abenteuerlich was du da machst.



  • Die spannende Frage ist doch im Grunde, was dir malloc als Typ zurückliefert, oder ?



  • SeppJ schrieb:

    Ja, das kannst du machen. Du solltest dir aber natürlich sicher sein, dass das alles korrekt abläuft, wenn du solche Casts verwenden willst.

    Der Compiler versucht dich hier davor zu bewahren den volatile Speicherbereich freizugeben, da er annehmen muss, dass dieser noch durch irgendeine ihm unbekannte Quelle benutzt wird (genau das sagt das volatile ja aus). Wenn du dir sicher bist, dass dies nicht der Fall ist, kannst du ihn auch freigeben.

    Aber irgendwie muss man ihn ja freigeben,
    Schreiben in das Array tut nur der Interrupt. Die Werte werden allerdings vom eigentlichen Programmprozess ausgelesen. Der Programmprozess gibt den Speicher frei. Er setzt der Interrupt vorher aus.

    P.S.: Klingt wirklich extrem abenteuerlich was du da machst.

    Es geht so. Schönes Programmieren ist halt an manchen Stellen (wenn es hardwarenah wird) nicht wirklich möglich, da vieles von der API einfach nicht für C++ erstellt wurde und sehr bescheuert in OO einzubauen ist.



  • Paul Manns schrieb:

    template <typename sensor_type> struct PWMSensorArray
    {
       // ...
        volatile value_type * volatile values;
    };
    

    Die Daten und der Pointer "values" müssen volatile qualifiziert sein, da hier Werte von einem Interrupt reingeschrieben werden.

    Das mag jetzt Haarspalterei sein, aber sollte hier nicht volatile value_type * values ausreichen? Der Interrupt schreibt ja, wenn ich dich richtig verstehe, nur in das Array, ändert aber nicht den Pointer selbst.

    Aus Sicht deines Compilers dürfte das Problem damit allerdings auch nicht gelöst sein, denn der scheint ja das andere, noch übrige volatile zu bemängeln.



  • dooooomi schrieb:

    Das mag jetzt Haarspalterei sein, aber sollte hier nicht volatile value_type * values ausreichen? Der Interrupt schreibt ja, wenn ich dich richtig verstehe, nur in das Array, ändert aber nicht den Pointer selbst.

    Ja stimmt. Ich mach's glaub ich weg, sonst steht mir der Kopf vor lauter volatile sonstwo.


Anmelden zum Antworten