Frage zu malloc()



  • Hallo,

    ich hab hier gerade folgenden Code vor mir:

    int *memorySpace = (int*) malloc(sizeof(int));
    cout << memorySpace << endl;
    

    Ich hab noch ein Verständnisproblem mit dem malloc()... was genau gibt mir das jetzt zurück? Über das cout bekomme ich eine Adresse ausgegeben, ist das jetzt die "Startadresse" für meine vier Byte die ich angefordert habe?

    Thx & Lg
    buzzzzzz, der ein wenig auf der Leitung steht 😃



  • das ist die adresse des ints, den du angefordert hast.



  • Benutze kein malloc in C++ (es sei denn, du kannst es gut begründen).


  • Mod

    manni66 schrieb:

    Benutze kein malloc in C++ (es sei denn, du kannst es gut begründen).

    Und bevor du nach dem C++-Äquivalent von malloc fragst: Nutze auch kein new! Laufzeitdynamik macht man in C++ gänzlich anders. malloc/new existieren zwar, aber sollten in Anwendercode nie auftauchen.



  • Hallo,

    danke für eure Antworten, es geht mir jetzt nur um das prinzipielle Verständnis von malloc().

    @noname66551: Das heißt, meine vier angeforderten Bytes (bzw. mehr Bytes bei einem anderen Datentyp) liegen in der besagten Adresse. Hab ich das so richtig verstanden?

    Ich habs irgendwo mal so aufgeschnappt, dass die zurückgegebene Adresse der "Startpunkt" für meine vier Bytes ist und demnach eben irgendwo wieder "enden" muss... ist wohl Blödsinn 😃

    Dann gleich noch eine Frage an SeppJ:
    new kenn ich natürlich, warum ist es so schlecht es in der Laufzeitdynamik zu verwenden?

    Thx & Lg


  • Mod

    buzz_lightzyear schrieb:

    Dann gleich noch eine Frage an SeppJ:
    new kenn ich natürlich, warum ist es so schlecht es in der Laufzeitdynamik zu verwenden?

    Weil man es falsch machen kann. Bei den üblichen Mechanismen (beispielsweise wie die ganze STL aufgebaut ist), kann dies nicht passieren. Da effektiv alles exakt das gleiche macht, gibt es daher keinen einzigen Grund für new.



  • buzz_lightzyear schrieb:

    @noname66551: Das heißt, meine vier angeforderten Bytes (bzw. mehr Bytes bei einem anderen Datentyp) liegen in der besagten Adresse. Hab ich das so richtig verstanden?

    Ich habs irgendwo mal so aufgeschnappt, dass die zurückgegebene Adresse der "Startpunkt" für meine vier Bytes ist und demnach eben irgendwo wieder "enden" muss... ist wohl Blödsinn 😃

    Du hast nicht vier Byte angefordert, sondern Speicher für einen int. Der KANN 4 Byte groß sein, muss aber nicht.
    Und ... natürlich ist die zurückgegebene Adresse der Startpunkt Deines angeforderten Speicherbereichs. 'In der besagten Adresse' - was soll das heißen?
    An der besagten Adresse liegt das erste Byte des Speichers, den Du angefordert hast, das zweite Byte liegt eine Adresse weiter, usw.



  • Belli schrieb:

    An der besagten Adresse liegt das erste Byte des Speichers, den Du angefordert hast, das zweite Byte liegt eine Adresse weiter, usw.

    Bei aktuellen Desktop Rechner mit x86 bzw. x64 Architektur sind die Speicherregister doch eben nicht nur ein Byte groß sondern 4, respektive 8 Byte.

    buzz_lightzyear würde also die Adresse des reservierten int zurückbekommen.

    Es ist aber auch möglich einen größeren Speicherblock zu reservieren (z.B. ein Array)

    int* p_array = (int *)malloc(sizeof(int)*50);
    

    In dem Fall beinhaltet der Pointer die Adresse des ersten int. (aka Startadresse des reservierten Speichers)



  • Schlangenmensch schrieb:

    Belli schrieb:

    An der besagten Adresse liegt das erste Byte des Speichers, den Du angefordert hast, das zweite Byte liegt eine Adresse weiter, usw.

    Bei aktuellen Desktop Rechner mit x86 bzw. x64 Architektur sind die Speicherregister doch eben nicht nur ein Byte groß sondern 4, respektive 8 Byte.

    buzz_lightzyear würde also die Adresse des reservierten int zurückbekommen.

    Also angenommen, er bekäme zurück

    0xabcd00
    

    dann wäre das nicht die Adresse eines Byte?
    Also bei

    0xabcd01
    

    (eine Adresse weiter) läge dann das nächste int?



  • Ich muss mich teilweise korrigieren. Offensichtlich wird doch Byte-weise adressiert.
    Trotzdem ist aus Adresse und Typ klar, dass an der Adresse ein Int liegt und dann das nächste Int dann 4 Bytes (abhängig von Architektur) weiter.

    int* memory = (int*)malloc(2*sizeof(int));
    std::cout << memory << std::endl;
    std::cout << ++memory << std::endl;
    free(--memory);
    
    int* newMemory = new int(2);
    std::cout << newMemory << std::endl;
    std::cout << ++newMemory << std::endl;
    delete[] --newMemory;
    
    int mem[2];
    std::cout << &mem[0] << std::endl;
    std::cout << &mem[1] << std::endl;
    

    führt bei mir zur Ausgabe:

    0018DEF8
    0018DEFC
    0018D5F8
    0018D5FC
    003DFD20
    003DFD24



  • Schlangenmensch schrieb:

    Ich muss mich teilweise korrigieren. Offensichtlich wird doch Byte-weise adressiert.
    Trotzdem ist aus Adresse und Typ klar, dass an der Adresse ein Int liegt und dann das nächste Int dann 4 Bytes (abhängig von Architektur) weiter.

    Klar, vielleicht ist es deutlicher, wenn man sagt, dass ab der Adresse ein int liegt. Jedenfalls reserviert malloc einen Speicherbereich von der Größe eines int und gibt einen Zeiger auf den Beginn, also auf das erste Byte, zurück.


  • Mod

    Wichtig: Speicher hat keinen Typ. Da liegt also kein Speicher vom Typ int, sondern bloß genügend Platz für einen. Die Interpretation, dass der Inhalt als int aufzufassen ist, kommt allein dadurch, dass der hier benutzte Zeiger vom Typ int* ist. Und daher kommt es auch, dass der hier benutzte Zeiger bei Inkrement stets um genau die Größe eines ints erhöht wird.



  • SeppJ schrieb:

    Wichtig: Speicher hat keinen Typ.

    Der von malloc() kommt schon. Der ist nämlich "void", denn malloc liefert einen void*, eine Adresse auf Beliebiges* 😉

    Auf was der Pointer zeigt, wird dann später später mit einem Cast bestimmt.

    ) Aus diesem Grund kann man auch nichts zu einem rohen void addieren oder abziehen. Da streikt der Compiler.



  • Andromeda schrieb:

    SeppJ schrieb:

    Wichtig: Speicher hat keinen Typ.

    Der von malloc() kommt schon. Der ist nämlich "void", denn malloc liefert einen void*, eine Adresse auf Beliebiges* 😉

    Quatsch.
    void ist kein Typ.
    void* ist ein Typ.



  • Wutz schrieb:

    Andromeda schrieb:

    SeppJ schrieb:

    Wichtig: Speicher hat keinen Typ.

    Der von malloc() kommt schon. Der ist nämlich "void", denn malloc liefert einen void*, eine Adresse auf Beliebiges* 😉

    Quatsch.
    void ist kein Typ.
    void* ist ein Typ.

    Kann man sich drüber streiten ... 😉

    C-Std, 6.2.5 Types:

    19 The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf


  • Mod

    Andromeda schrieb:

    Kann man sich drüber streiten ... 😉

    Nein, kann man nicht. void ist die Abwesenheit eines Typen. Zu sagen, dass der Speicher void-Typ hätte, ist zu sagen, dass er keinen Typen hat. Was korrekt ist.



  • SeppJ schrieb:

    Andromeda schrieb:

    Kann man sich drüber streiten ... 😉

    Nein, kann man nicht. void ist die Abwesenheit eines Typen.

    Das ist eine philosophische Frage, vergleichbar mit der Fragestellung, ob das Nichts existiert, oder ob Atheismus ein Glaube ist und so.


  • Mod

    Ich: Speicher hat keinen Typen.
    Du: Doch, Speicher hat den Typ, keinen Typ zu haben!
    😕



  • SeppJ schrieb:

    Ich: Speicher hat keinen Typen.
    Du: Doch, Speicher hat den Typ, keinen Typ zu haben!
    😕

    Ja, hier erklärt das jemand ziemlich gut:

    Yes, void is a type. Whether it's a data type depends on how you define that term; the C standard doesn't.

    The standard does define the term "object type". In C99 and earlier; void is not an object type; in C11, it is. In all versions of the standard, void is an incomplete type. What changed in C11 is that incomplete types are now a subset of object types; this is just a change in terminology. (The other kind of type is a function type.)

    C99 6.2.6 paragraph 19 says:

    The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

    The C11 standard changes the wording slightly:

    The void type comprises an empty set of values; it is an incomplete object type that cannot be completed.

    This reflects C11's change in the definition of "object type" to include incomplete types; it doesn't really change anything about the nature of type void.

    The void keyword can also be used in some other contexts:

    As the only parameter type in a function prototype, as in int func(void), it indicates that the function has no parameters. (C++ uses empty parentheses for this, but they mean something else in C.)

    As the return type of a function, as in void func(int n), it indicates that the function returns no result.

    void* is a pointer type that doesn't specify what it points to.

    In principle, all of these uses refer to the type void, but you can also think of them as just special syntax that happens to use the same keyword.

    http://stackoverflow.com/questions/3487689/is-void-a-data-type-in-c


  • Mod

    Andromeda schrieb:

    SeppJ schrieb:

    Wichtig: Speicher hat keinen Typ.

    Der von malloc() kommt schon. Der ist nämlich "void", denn malloc liefert einen void*, eine Adresse auf Beliebiges* 😉

    Auf was der Pointer zeigt, wird dann später später mit einem Cast bestimmt.

    ++Verwirrung
    --Klarheit

    Ja was denn nun? Du musst dich schon festlegen, ob du sagen willst, das malloc den Typ bestimmt - dann widersprichst du dir selber gleich im nächsten Satz. Oder der Typ wird eben tatsächlich erst später festgelegt, und malloc hat nichts damit zu tun. Oder aber der Typ wechselt je nach Verwendung, was impliziert, das der Typ eben keine Eigenschaft des rohen Speichers als solchen sein kann, was ungefähr das sein dürfte, was SeppJ gemeint hat.

    Mehr Denken, weniger Smileys.


Anmelden zum Antworten