Wie gut kennst Du Deine Sprache, Deinen Compiler und Dein Zielsystem?
Allgemein:
Es richtet sich in erster Linie an Programmierer für x86, x86_64 (aka "übliche Desktop und Notebookhardware"), die es vorziehen (müssen
), den Speicher selbstständig zu verwalten.
Die Fragen sind an sich an keine konkrete Sprache, Compiler oder Laufzeitbibliothek gebunden und die Antworten können nur eure Lieblingssprache + Lieblingsplattform + Lieblingscompiler + Laufzeitbibliothek beinhalten.
Z.B schreibt jemand seine Programme in C für Ubuntu X - amd64 und benutzt GCC und glibc. Dann kann derjenige schreiben:
Antwort(en) für: C mit gcc 4.8 auf Ubuntu X amd64, glibc foo (oder "default").
Natürlich könnt ihr auch weitere Sprachen, Plattformen usw. hinzufügen
.
Idealerweise beantwortet ihr "wahrheitsgemäß" erstmal alle Fragen "aus dem Stand", bevor ihr euch an die konkrete Umsetzung macht.
Eure Antworten, Code und (hoffentlich
) beigefügte Erklärungen, warum das so ist, bitte in Spoilern posten:
[ spoiler=foo ] [ /spoiler ] (ohne Leerzeichen)
Fragen und Teilaufgaben, die eurer Meinung nach für eure Plattform/Sprache keinen Sinn ergeben oder nicht umsetzbar sind, könnt ihr auslassen.
Allgemein:
Es richtet sich in erster Linie an Programmierer für x86, x86_64 (aka "übliche Desktop und Notebookhardware"), die es vorziehen (müssen

Die Fragen sind an sich an keine konkrete Sprache, Compiler oder Laufzeitbibliothek gebunden und die Antworten können nur eure Lieblingssprache + Lieblingsplattform + Lieblingscompiler + Laufzeitbibliothek beinhalten.
Z.B schreibt jemand seine Programme in C für Ubuntu X - amd64 und benutzt GCC und glibc. Dann kann derjenige schreiben:
Antwort(en) für: C mit gcc 4.8 auf Ubuntu X amd64, glibc foo (oder "default").
Natürlich könnt ihr auch weitere Sprachen, Plattformen usw. hinzufügen

Idealerweise beantwortet ihr "wahrheitsgemäß" erstmal alle Fragen "aus dem Stand", bevor ihr euch an die konkrete Umsetzung macht.
Eure Antworten, Code und (hoffentlich

[ spoiler=foo ] [ /spoiler ] (ohne Leerzeichen)
Fragen und Teilaufgaben, die eurer Meinung nach für eure Plattform/Sprache keinen Sinn ergeben oder nicht umsetzbar sind, könnt ihr auslassen.
Frage 1:
Wenn man sich den Speicherverbrauch seines Programms mittels ps, processexplorer usw. anzeigen lässt, wird grob gesehen zwischen dem virtuellen und physikalischen Speicher unterschieden.
Welche Werte sind für den Endanwender eigentlich relevant? Warum?
Wenn man sich den Speicherverbrauch seines Programms mittels ps, processexplorer usw. anzeigen lässt, wird grob gesehen zwischen dem virtuellen und physikalischen Speicher unterschieden.
Welche Werte sind für den Endanwender eigentlich relevant? Warum?
"Antwort aus dem Stand"
a) Du forderst einen 1024*1024*1024 Bytes = 1GiB großen Speicherblock an
1) uninitialisiert, mittels malloc (oder äquivalenter Möglichkeit Deiner Sprache)
2) mit 0-en vorinitialisiert, mittels calloc
3) unitialisiert mittels malloc und initialisierst diesen mit 1
4) mit 0-en vorinitialisiert, mittels calloc und initialisierst diesen mit 1
Wie viel virtuellen und wie viel physikalischen Speicher wird die Anwendung nun jeweils zusätzlich belegen? (Es interessiert uns also nur, wie viel "hinzukommt").
Für diese und nachfolgende Fragen gilt: da eine exakte Messung nicht immer möglich ist und zudem oft einen eigenen Streitpunkt darstellt, reicht eine ungefähre Antwort aus. Ferner gehen wir davon aus, dass unser verfügbarer RAM groß genug ist und nichts im Swap landet.
b) Du gibst den Speicher mittels "free" (oder was auch immer) frei. Wie viel virtuellen und physikalischen Speicher wird im jeweiligen Fall Deiner Schätzung nach freigegeben?
c) setze a) und b) in insgesamt 4 Programmen um (Speicheranforderung und Freigabe in einem Programm), falls nötig, kann die angeforderte Blockgröße reduziert werden.
Nun miss nach (die write("Nachricht");readchar() aus dem Muster sollten dafür hilfreich sein)
Stimmen die Ergebnisse mit den Antworten aus a) und b) in etwa überein? Falls nein, was könnte die Ursache dafür sein?
a) Du forderst einen 1024*1024*1024 Bytes = 1GiB großen Speicherblock an
1) uninitialisiert, mittels malloc (oder äquivalenter Möglichkeit Deiner Sprache)
2) mit 0-en vorinitialisiert, mittels calloc
3) unitialisiert mittels malloc und initialisierst diesen mit 1
4) mit 0-en vorinitialisiert, mittels calloc und initialisierst diesen mit 1
Wie viel virtuellen und wie viel physikalischen Speicher wird die Anwendung nun jeweils zusätzlich belegen? (Es interessiert uns also nur, wie viel "hinzukommt").
Für diese und nachfolgende Fragen gilt: da eine exakte Messung nicht immer möglich ist und zudem oft einen eigenen Streitpunkt darstellt, reicht eine ungefähre Antwort aus. Ferner gehen wir davon aus, dass unser verfügbarer RAM groß genug ist und nichts im Swap landet.
b) Du gibst den Speicher mittels "free" (oder was auch immer) frei. Wie viel virtuellen und physikalischen Speicher wird im jeweiligen Fall Deiner Schätzung nach freigegeben?
c) setze a) und b) in insgesamt 4 Programmen um (Speicheranforderung und Freigabe in einem Programm), falls nötig, kann die angeforderte Blockgröße reduziert werden.
Code:
write("Vor der Speicheranforderung");
readchar();
res = malloc(1024*1024*1024);
write("Speicher wurde angefordert, wird gleich freigegeben");
readchar();
free(res);
write("Speicher wurde freigegeben");
readchar();
Nun miss nach (die write("Nachricht");readchar() aus dem Muster sollten dafür hilfreich sein)
Stimmen die Ergebnisse mit den Antworten aus a) und b) in etwa überein? Falls nein, was könnte die Ursache dafür sein?
"Antwort aus dem Stand"
a) Du forderst insgesamt 1024*1024*1024 Bytes = 1GiB Speicher an,
allerdings 1024*1024 Blöcke je 1024 Bytes.
1)uninitialisiert
2)initialisierst in jedem Block das erste Byte mit 1
Wie viel virtuellen und wie viel physikalischen Speicher wird die Anwendung nun jeweils zusätzlich belegen?
b) Du gibst nun 3/4 aller Blöcke (von 1024*1024/4 bis 1024*1024) wieder frei.
Wie viel virtuellen und physikalischen Speicher wird im jeweiligen Fall Deiner Schätzung nach freigegeben?
c) Du gibst nun 3/4 alle Blöcke frei, allerdings "der Reihe nach" - Du behältst also jeden vierten Block:
Wie viel virtuellen und physikalischen Speicher wird im jeweiligen Fall Deiner Schätzung nach freigegeben?
d) Setze a) mit jeweils unterschiedlichen Freigabestrategien aus b) und c) um. Falls nötig, kann die Anzahl der Blöcke reduziert werden.Miss nach. Stimmen die Ergebnisse mit den Antworten aus a), b) und c) in etwa überein? Falls nein, was könnte die Ursache dafür sein?
a) Du forderst insgesamt 1024*1024*1024 Bytes = 1GiB Speicher an,
allerdings 1024*1024 Blöcke je 1024 Bytes.
1)uninitialisiert
2)initialisierst in jedem Block das erste Byte mit 1
Wie viel virtuellen und wie viel physikalischen Speicher wird die Anwendung nun jeweils zusätzlich belegen?
b) Du gibst nun 3/4 aller Blöcke (von 1024*1024/4 bis 1024*1024) wieder frei.
Wie viel virtuellen und physikalischen Speicher wird im jeweiligen Fall Deiner Schätzung nach freigegeben?
c) Du gibst nun 3/4 alle Blöcke frei, allerdings "der Reihe nach" - Du behältst also jeden vierten Block:
Code:
for i=0 to 1024*1024:
block[i]=malloc(1024);
...
for i=0 to 1024*1024:
if (i mod 4 != 0): free(block[i]);
d) Setze a) mit jeweils unterschiedlichen Freigabestrategien aus b) und c) um. Falls nötig, kann die Anzahl der Blöcke reduziert werden.Miss nach. Stimmen die Ergebnisse mit den Antworten aus a), b) und c) in etwa überein? Falls nein, was könnte die Ursache dafür sein?
Ab und zu wird das Lesen von einem Socket oder STDIN so umgesetzt:
Ist dieser Code (bezüglich der Speichermanipulation und Effizienz) ok/akzeptabel? Falls nein, warum nicht?
Code:
int count = 0;
char* block = malloc(1);
int inp;
...
do{
inp = read_one_char_from_sock_or_stdin();
block[count] = (char) inp;
block = realloc(count + 1);
count++;
}while (inp != END);