Initialisiert malloc() das zugewiesene Array auf Null?

Lesezeit: 5 Minuten

Benutzeravatar von devil0150
Teufel0150

Hier ist der Code, den ich verwende:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr;
    int sz = 100000;
    arr = (int *)malloc(sz * sizeof(int));

    int i;
    for (i = 0; i < sz; ++i) {
        if (arr[i] != 0) {
            printf("OK\n");
            break;
        }
    }

    free(arr);
    return 0;
}

Das Programm druckt nicht OK. malloc soll den zugewiesenen Speicher nicht auf Null initialisieren. Warum passiert das?

  • Der Inhalt des Speichers ist unbestimmt. Es könnte scheinbar zufällig sein. Oder es könnte alle Nullen sein. Man weiß es vorher einfach nicht.

    – Irgendein Programmierer-Typ

    26. Juli 2017 um 10:14 Uhr

  • „Das Programm druckt nicht OK. malloc soll den zugewiesenen Speicher nicht auf Null initialisieren.“ – Es soll es auch nicht garantieren ist nicht alles null. In jedem Fall hat Ihr Programm durch das Lesen unbestimmter Werte ein undefiniertes Verhalten. Du kannst nichts erwarten.

    – StoryTeller – Unslander Monica

    26. Juli 2017 um 10:16 Uhr


  • Außerdem können Debug-Builds tatsächlich dazu führen, dass Sie Speicher oder sogar lokale Variablen zuweisen sein initialisiert. Damit Speicher- und Zeigerprobleme leichter erkannt werden können.

    – Irgendein Programmierer-Typ

    26. Juli 2017 um 10:16 Uhr

  • @Someprogrammerdude – Ob ein Typ Trap-Werte hat oder nicht, wird nicht durch den C-Standard definiert. Und wenn ein Trap-Wert gelesen wird, ist das Verhalten explizit undefiniert. Ich glaube also, es ist überall UB.

    – StoryTeller – Unslander Monica

    26. Juli 2017 um 10:25 Uhr

  • @StoryTeller Da hast du wahrscheinlich einen Punkt.

    – Irgendein Programmierer-Typ

    26. Juli 2017 um 10:27 Uhr

Benutzeravatar von msc
msc

Die Manpage von malloc sagt:

Die Funktion malloc() weist Größenbytes zu und gibt einen Zeiger auf den zugeordneten Speicher zurück. Der Speicher wird nicht initialisiert. Wenn size 0 ist, gibt malloc() entweder NULL oder einen eindeutigen Zeigerwert zurück, der später erfolgreich an free() übergeben werden kann.

So malloc() kehrt zurück nicht initialisierter Speicherderen Inhalt unbestimmt ist.

 if (arr[i] != 0)

Sie haben in Ihrem Programm versucht, auf den Inhalt eines aufgerufenen Speicherblocks zuzugreifen undefiniertes Verhalten.

  • Der letzte Absatz ist nicht korrekt. Die bloße Verwendung eines unbestimmten Werts führt nicht zwangsläufig zu undefiniertem Verhalten. Es kann jedoch sehr unregelmäßig sein. Es wird zu einem undefinierten Verhalten, wenn Sie es an eine Bibliotheksfunktion übergeben.

    – Antti Haapala – Слава Україні

    29. September 2019 um 19:00 Uhr

Benutzeravatar von axiac
axiac

malloc soll den zugewiesenen Speicher nicht auf Null initialisieren. Warum passiert das?

So wurde es vor mehr als 40 Jahren konzipiert.

Aber gleichzeitig die calloc() Funktion wurde erstellt initialisiert den zugewiesenen Speicher auf Null und es ist die empfohlene Methode, um Speicher für Arrays zuzuweisen.

Die Linie:

arr = (int *)malloc(sz * sizeof(int));

Sollte lesen:

arr = calloc(sz, sizeof(int));

Wenn Sie C aus einem alten Buch lernen, lehrt es Sie, immer den von zurückgegebenen Wert umzuwandeln malloc() oder calloc() (a void *) auf den Typ der Variablen, der Sie den Wert zuweisen (int * in Ihrem Fall). Dies ist obsolet, wenn der Rückgabewert von malloc() oder calloc() direkt einer Variablen zugewiesen wird, benötigen die modernen Versionen von C diese Umwandlung nicht mehr.

  • GCC-Dokumentation: Die Umwandlung ist in anderen Kontexten als Zuweisungsoperatoren erforderlich.

    – Ryan B.

    26. Juli 2017 um 10:38 Uhr

  • @RyanB. – GCC ist hier nicht C-Standard-konform. void* ist implizit in alle Objekttypen konvertierbar. Keine Besetzung erforderlich.

    – StoryTeller – Unslander Monica

    26. Juli 2017 um 10:49 Uhr


Benutzeravatar von hackks
hackt

malloc soll den zugewiesenen Speicher nicht auf Null initialisieren.

Speicher zugewiesen von malloc ist nicht initialisiert. Der Wert an diesen Standorten ist unbestimmt. In diesem Fall kann der Zugriff auf diesen Speicher zu einem undefinierten Verhalten führen, wenn der Wert an dieser Stelle eine Trap-Darstellung für den Typ sein soll.

n1570-§6.2.6.1 (p5):

Bestimmte Objektdarstellungen müssen keinen Wert des Objekttyps darstellen. Wenn der gespeicherte Wert eines Objekts eine solche Darstellung hat und von einem lvalue-Ausdruck gelesen wird, der keinen Zeichentyp hat, ist das Verhalten undefiniert. […]

und Fußnote sagt:

Somit kann eine automatische Variable mit einer Trap-Darstellung initialisiert werden, ohne undefiniertes Verhalten zu verursachen, aber der Wert der Variablen kann nicht verwendet werden, bis ein richtiger Wert darin gespeichert ist.

Es kann nichts Gutes erwartet werden, wenn das Verhalten undefiniert ist. Sie können das erwartete Ergebnis erhalten oder nicht.

Benutzeravatar von Ryan B
Ryan B.

Aus dem C-Standard 7.22.3.4:

Zusammenfassung

#include <stdlib.h>
void *malloc(size_t size);

Beschreibung

Die Funktion malloc weist einem Objekt Speicherplatz zu, dessen Größe durch size angegeben wird und dessen Wert unbestimmt ist.

Der Wert ist unbestimmt. Es steht also jedem Compiler frei, sich zu verhalten, wie er will. Beispielsweise in Microsoft Visual C++ in Debug Modus, der Bereich des zugewiesenen Speichers durch malloc() ist alles eingestellt 0xCDCDCDCD und wann drin Release Modus ist es zufällig. In modernen Versionen von GCC wird es auf 0x000000 gesetzt, wenn Sie keine Codeoptimierungen aktivieren, und ansonsten zufällig. Ich weiß nichts über andere Compiler, aber Sie bekommen die Idee.

Benutzeravatar von babon
Pavian

void *malloc(size_t size) soll nur den angegebenen Platz freihalten. Das ist alles. Es gibt keine Garantie dafür, was in diesem Raum vorhanden sein wird.

Zitat aus den Manpages:

Das malloc() Die Funktion weist Größenbytes zu und gibt einen Zeiger auf den zugeordneten Speicher zurück. Der Speicher wird nicht initialisiert. Wenn size ist dann 0 malloc() gibt entweder NULL oder einen eindeutigen Zeigerwert zurück, an den später erfolgreich übergeben werden kann free().

Außer, abgesondert, ausgenommen calloc() du kannst den … benutzen memset() Funktion, um einen Speicherblock auf Null zu setzen.

Benutzeravatar von Luis Colorado
Luis Colorado

Beim ersten Anruf malloc(3)fordert es das Betriebssystem auf, Speicher für den Heap-Speicherplatz zu erhalten.

Aus Sicherheitsgründen setzt der Unix/Linux-Kernel (und viele andere Betriebssysteme) im Allgemeinen den Seiteninhalt, der an einen Prozess übergeben werden soll, auf Null, sodass kein Prozess auf den vorherigen Inhalt dieses Speichers zugreifen und unangenehme Dinge damit anstellen kann (wie die Suche nach alte Passwörter oder ähnliches).

Wenn Sie mehrere Zuweisungen und Freigaben von Speicher vornehmen und das malloc-Modul den vorherigen Speicher wiederverwendet, werden Sie sehen, dass Müll von kommt malloc(3).

Benutzeravatar von kalaiamuthan manisekar
kalaiamuthan manisekar

Nullen werden den Seiteninhalten beim ersten Mal im Linux-Kernel zugewiesen.

Das folgende Programm erklärt den Unterschied bei der Speicherinitialisierung in malloc und calloc:

#include<stdio.h>
#include<stdlib.h>

#define SIZE 5

int main(void) {
    int *mal = (int*)malloc(SIZE*sizeof(int));
    int *cal = (int*)calloc(SIZE, sizeof(int));

    mal[4] = cal[4] = 100;

    free(mal); free(cal);

    mal = (int*)malloc(SIZE*sizeof(int));
    cal = (int*)calloc(SIZE, sizeof(int));

    for(int i=0; i<SIZE; i++) {
        printf("mall[%d] = %d\n", i, mal[i]);
    }
    for(int i=0; i<SIZE; i++) {
        printf("call[%d] = %d\n", i, cal[i]);
    }
}

1432960cookie-checkInitialisiert malloc() das zugewiesene Array auf Null?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy