static in Kombination mit Zeiger und malloc



  • Hallo,

    ich arbeite mit einem Programm, in dem folgender Code auftaucht:

    void funcA (void)
    static double *fa;
    fa = malloc(100 * sizeof(*fa));
    ...
    

    Dazu eine kurze Verständnisfrage, ohne näher darauf einzugehen, was das Programm genau macht. Bin mir nämlich nicht sicher, ob ich den Gebrauch von static bei Pointern richtig verstanden habe.
    In der Weise, wie fa verwendet wird, macht es doch keinen Sinn fa als static zu deklarieren. Also es ist nicht falsch, aber der eigentliche Effekt von static wird nicht genutzt.
    Weil mit malloc wird fa zu Beginn von funcA doch jedesmal ein neuer Bereich zugeteilt, oder? Das heißt bei nem eventuellen zweiten Aufruf von funcA wird zwar fa mit der alten Adresse auch aufgerufen, aber dann gleich überschrieben.

    2. Frage: In dem Beispiel hier war ja der Zeiger selbst static. Wie ist das denn, wenn der Zeiger auf eine Variable zeigt, die static ist. Muss man da etwas berücksichtigen?

    Danke schonmal



  • Am besten Du zeigst mal etwas richtigen Code, und nicht nur nicht zusammenhängende Schnipsel 😉



  • Absolute Grundlagen:
    Der Speicherklassenspezifizierer static regelt in Abhängigkeit davon, ob er innerhalb/außerhalb eines compound blocks '{}' gebraucht wird, die Sichtbarkeit oder den Initialwert.
    - innerhalb: hier ist die Sichtbarkeit klar, deshalb impliziert die Angabe von static hier einen Initialwert = 0
    - außerhalb: hier wird die Sichtbarkeit geregelt, da hier der Initialwert sowieso schon immer = 0 ist (globale Variable!), d.h. die Angabe von static beschränkt die Sichtbarkeit auf die aktuelle *.c Datei



  • Hier mal ein bisschen ausführlicher:

    void funcA (void) {
    static double *fa;
    fa = malloc(100 * sizeof(*fa));
    ...
    }
    
    int main (void) {
    funcA();
    ...
    }
    

    Aus der Antwort von Wutz werde ich trotzdem nicht ganz schlau. Ich hab ja den Fall, dass static innerhalb eines compound blocks gebraucht wird. Das static auch regelt, ob eine Variable anfangs einen Zufallswert hat oder 0 bekommt, wusste ich nicht, habe ich aber jetzt glaube ich verstanden.
    Mein Beispiel ist ja mit nem Zeiger. Ich verstehe nicht, warum man den static macht, aber ihm dann als allererstes per malloc einen Speicherbereich übergibt. Wird funcA ein zweites Mal aufegerufen, kriegt fa auch einen neuen Bereich.



  • Ist mir auch ein wenig schleierhaft, wenn da kein free vorkommt, gibt es ein Speicherleck. Wenn der Zeiger zurückgegeben würde, würde es Sinn machen, ihn als static zu deklarieren.

    Wofür man einen Zeiger als static deklarieren könnte:

    void func()
    {
        static double * ptr;
        if(!ptr){ptr = (double*)malloc(100 * sizeof(double));} // Wird in idr. nur 1 mal ausgeführt
        // ...
    }
    


  • static hat in C zwei Bedeutungen:

    1. Einmal kann man static für globale Variablen festlegen, um den Scope (die Erreichbarkeit) in dem jeweiligen Modul (Quellcodedatei) festzulegen. Eine solche Variable besitzt dann keine Linkage mehr zu anderen Modulen (zumindest Dirk Louis nach). Für C++ benutzt man im Übrigen (oder wird zumindest empfohlen) den sog. namenlosen Namespace (im Grunde ein Namensbereich, in dem nur Sachen vorkommen, die man auch mit static hätte deklarieren können, die also nur im jeweiligen Modul vor).

    2. Auch für lokale Variablen kann man die static -Speicherklasse festlegen. Dabei legt man den Scope nur für die Funktion, in der sie deklariert wurde, fest - die Anweisung, in der die Variable deklariert wurde, wird nur einmal gelesen, danach ignoriert (oder taucht im Code sogar nicht mehr vor? Weiß ich jetzt nicht genau). Allerdings wird NUR der Scope eingeschränkt, der Speicher bleibt beim Verlassen der Funktion erhalten, somit auch der Wert.

    In deinem Beispiel wird ein static -Zeiger definiert, ABER NICHT INITIALISIERT, was im Grunde den Nutzen einer static -Deklaration untergräbt. Denn der Wert der Variable bleibt nicht erhalten, sondern wird immer neu zugewiesen (wenn ihr denn was zugewiesen wird). Böse wird es, wenn es sich nicht um eine relativ harmlose Variable auf dem Stack, sondern um einen Zeiger handelt:

    void foo()
    {
        static int*pInt=malloc(sizeof(int)); //Braucht nicht, sollte sogar nicht freigegeben werden (es sei denn, das Programm wird beendet, aber dann macht's eh keinen Unterschied mehr).
        static float*pFloat; //Uninitialisierter Zeiger.
        pFloart=malloc(sizeof(float)); //Wenn nicht freigegeben wird, gibt es ein Speicherleck.
    

    Man kann natürlich überprüfen, ob der Zeiger schon initialisiert wurde (soweit ich weiß, werden static -Variablen standardmässig mit 0 initialisiert, aber sicher bin ich nicht so sehr), aber das wäre eine unnötige Maßnahme, wenn man den Zeiger initialisieren würde und ihm nicht später eine Adresse zuweist (zwischen Zuweisung und Initialisierung besteht ein Unterschied). Diese würde bei einer Initialisierung erhalten bleiben.


Anmelden zum Antworten