Forum: PC-Programmierung C - Array Zugriff außerhalb Definition, keine Speicherverletzung?!


von Müller (Gast)


Lesenswert?

Hallo liebes Forum,

ich habe wieder eine Frage bezüglich der C-Programmierung. Zurzeit sind 
wir in der Techniker Schule beim Thema Arrays und bearbeiten diverse 
Aufgaben.

Zuletzt war die Aufgabe eine Passworteingabe in der Konsole zu 
realisieren, wo man die Zeichen mittels * verstecken sollte. Eig. eine 
einfache Aufgabe wenn man das \b kennt.

Bei der Aufgaben Besprechung fiel mir auf, dass keinerlei Abfrage drinne 
war, in der man nach rechtzeitig ein beschreiben eines Arrays außerhalb 
seiner Größe verhinderte.

So habe ich dies angesprochen und gesagt wenn man nun mehr Zeichen 
eingibt als das Array groß ist, dass dies zu einer Speicherverletzung 
führt und das Programm abstürzen würde. Ich war dann ziemlich erstaunt 
als eben letzteres nicht eingetreten ist, als der Lehrer dies dann in 
seinem Musterprogramm tat. Was mir dann ziemlich peinlich war ;)

Plattform: Windows und IDE Dev CPP mit GCC.

Meine Lösung sah so aus:
1
// Nun lese das Passwort ein
2
        printf("\nBitte geben Sie nun das Passwort ein:\n");
3
4
        while((key = getch()) != 13)
5
        {
6
            // Backspace verarbeiten
7
            if(key == 8 && x > 0)
8
            {
9
                passwort[x] = 0;
10
                x--;
11
                printf("\b \b");
12
            }
13
            // Zeichen verarbeiten
14
            else if(key != 8 && x <= size-2)
15
            {
16
                passwort[x] = key;
17
                x++;
18
                printf("*");
19
            }
20
            // Wurden mehr als 18 Zeichen eingegeben? Dann breche ab
21
            else if(x > size-2)
22
            {
23
                break;
24
            }
25
            // Wenn noch nix eingegeben wurde und Backspace gedrückt wurde.
26
            else
27
            {
28
                continue;
29
            }
30
        }
31
32
        daten.passwort[x] = '\0';



Nun danach hab ich mich damit nochmal beschäftigt und so Späßchen 
probiert:
1
char array[10];
2
array[14] = 'A';
3
printf("%c", array[14]);

Sowas wurde anstandslos kompiliert und ohne Fehler / Warnungen. Und 
seltsamerweise hat das auch noch funktioniert?!

Habe ich irgendwas verpasst oder optimiert der Compiler sowas 
automatisch????

Bisher dachte ich immer das wäre ein Buffer Overflow und muss 
aufjedenfall verhindert und abgefangen werden.

Hat jemand eine Idee?

Liebe Grüße
Müller

von Andreas B. (andreasb)


Lesenswert?

Müller schrieb:
>
> Nun danach hab ich mich damit nochmal beschäftigt und so Späßchen
> probiert:
>
1
char array[10];
2
array[14] = 'A';
3
printf("%c", array[14]);
>
> Sowas wurde anstandslos kompiliert und ohne Fehler / Warnungen. Und
> seltsamerweise hat das auch noch funktioniert?!

Dieses Array liegt auf dem Stack, auf dem Stack wird blockweise drauf 
gepackt, wenn eine Funktion aufgerufen wird, oder gelöscht, wenn diese 
Verlassen wird.

Auf einem 64bit System wird ziemlich sicher auf 8 byte gerundet, dein 
10er block wird somit warscheinlich schon mal auf 16byte aufgerundet.

Und mit 14 bis du in dieser Limite drin.

Google mal nach "stack canary", mit denen kann ein Buffer Overflow 
bedingt verhindert werden.

Und führe doch dein Experiment mal noch etwas weiter:
1
char array0[8];
2
char array[8];
3
char array1[8];
4
array[14] = 'A';
5
printf("%c", array[14]);

Was passiert wohl mit array0 und array1, wenn du eine Überschreitung in 
array machst?

[edit: Zitat Einrückung im Code entfernt]

mfg Andreas

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Müller schrieb:
> So habe ich dies angesprochen und gesagt wenn man nun mehr Zeichen
> eingibt als das Array groß ist, dass dies zu einer Speicherverletzung
> führt und das Programm abstürzen würde
Wenn das so wäre, wäre das ja alles einfach. Ist zB in Java oder .NET 
Sprachen so, da stürzt das Programm "sicher" ab in so einem Fall. Bei 
C(++) passiert bei einem solchen Buffer-Overflow halt einfach irgend 
etwas, wie zB das Überschreiben von anderen Variablen, der 
Rücksprung-Adresse, das Einschleusen von fremdem Code (der Grund für 
sehr viele Sicherheitslücken) usw. Die C(++) -Standards sagen einfach, 
das Verhalten ist "undefiniert". Deswegen ist es ja so wichtig, 
korrekten Code zu schreiben, weil man bei solchen Fehlern keinen 
"sicheren" Absturz garantieren kann. Unter Linux hilft zB das Programm 
"valgrind" beim Finden solcher Fehler.

von Dirk B. (dirkb2)


Lesenswert?

Müller schrieb:
> Bisher dachte ich immer das wäre ein Buffer Overflow und muss
> aufjedenfall verhindert und abgefangen werden.

Genau das passiert nicht.
In C werden keine Arraygrenzen überprüft.

Und das ist die große Gefahr bei C.

Es kann immer sein, dass Code der nicht richtig ist, zufällig 
funktioniert.
Du darfst davon keine Rückschlüsse auf andere Compiler/Systeme ziehen.

Dabei sollte man bedenken, das C von Profis für Profis (die Autoren) 
gemacht wurde.
Also für Leute, die wissen was sie tun.

C ist eine relativ einfache Sprache. Das heißt aber nicht, dass C 
einfach zu programmieren ist.

von A. H. (ah8)


Lesenswert?

Das Beschreiben eines Feldes außerhalb der definierten Grenzen führt zu 
einem undefinierten Verhalten und undefiniertes Verhalten heißt, dass 
alles möglich ist, auch dass das Programm (zumindest zunächst) so 
funktioniert, wie erwartet. Wenn Dein Lehrer Deinen Einwand in der Tat 
damit abgewiesen hat, dass es doch funktioniert, so sollte ihm das 
peinlich sein und nicht Dir, denn er sollte wissen, dass man durch Tests 
nur die Anwesenheit von Fehlern beweisen kann, aber niemals aber deren 
Abwesenheit. Dein Einwand war also (erst einmal) völlig richtig. 
(Vielleicht sollte das ja aber auch pädagogischer Trick um gezielt Dein 
Vertrauen in Tests zu erschüttern. Ob das zielführend ist, sei einmal 
dahin gestellt.)

Dein Irrtum liegt allerdings darin, dass es sehr wohl Abfragen zur 
Bereichsüberschreitung gibt. C prüft Bereichsüberschreitungen in der Tat 
nicht selbst, sondern überlässt das dem Programmierer. Das ist so 
gewollt. Die Ausdrücke
1
x > 0
und
1
x <= size-2
sind aber genau das, Abfragen zur Bereichsprüfung.

von Noch einer (Gast)


Lesenswert?

Wer Trojaner und Viren schreibt, nutzt solche Fehler aus.

Auf dem Stack sind Daten und Adressen für das return gemischt. So kann 
ein zu langes Passwort die Return-Adresse überschreiben. Das return 
springt dann an eine Stelle, die den Trojaner installiert.

Beim nächsten Mal nichts sagen - besser dem Dozenten einen Virus 
unterschieben, der ihn auf seinen Fehler hinweist.

von Müller (Gast)


Lesenswert?

Hallo zusammen,

vielen Dank für das Feedback und die Aufklärung. Das da Bereiche mit 
definierter Größe auf dem Stack reserviert werden, wusste ich nicht. Ist 
das nicht unnütze "Speicherverschwendung"? Wenn ich 6 Bytes haben will 
und der reserviert 8 Bytes? Okay 2 Bytes sind jetzt nicht die Welt, aber 
wenn man 10000 Variablen hat? Oder denkt man sich: "Och joah das 
Speichermanagment des OS regelt dat schoon..."

Wenn man Speicher dynamisch reserviert, wird ja auch nur soviel 
reserviert, wie ich gerne hätte.

Der Code Snipsel stammte von mir, die Musterlösung müsste ich nochmal in 
meinen Unterlagen nachschauen.

Dazu noch eine Frage, warum "programmiert" man nicht einen Compiler der 
sowas standardmäßig prüft in C? Zumindestens bei so offentsichtlichen 
Sachen, wie in meinen zweiten Snipsel?

Lieben Gruß
Müller

von Peter II (Gast)


Lesenswert?

Müller schrieb:
> Das da Bereiche mit
> definierter Größe auf dem Stack reserviert werden, wusste ich nicht. Ist
> das nicht unnütze "Speicherverschwendung"?

nein, denn wenn es mehr variabel werden kommen sie in den gleichen 
Block.

Je kleiner die Blöcke werden, desto langsamer ist die Speicherverwaltung 
weil viel mehr Blöcke verwaltet werden müssen.

von Noch einer (Gast)


Lesenswert?

>warum "programmiert" man nicht einen Compiler der
>sowas standardmäßig prüft in C?

Weil das Programm grösser und langsamer wird. Gibt unterschiedliche 
Programmiersprachen mit unterschiedlichen Prioritäten. Bei C ist halt 
absolut oberste Priorität - das Programm soll klein und schnell sein. 
Wer die Überprüfungen auf Programmiererfehler in seinem Programm haben 
will, benutzt andere Programmiersprachen.

Gibt Tools für statische Prüfungen, wie das alte lint. Die finden aber 
nur wenige Fehler.

Gibt auch Tools, die zur Laufzeit prüfen. Wie der oben bereits genannte 
"stack canary". Wird aber nur zum Test benutzt, im fertigen Programm 
wieder ausgebaut.

von Peter II (Gast)


Lesenswert?

Noch einer schrieb:
> Weil das Programm grösser und langsamer wird.

der Compiler soll den Fehler melden, das ändert also nichts am Programm. 
Mich wundert auch das der GCC nicht mal eine Warnung ausgibt.

von Noch einer (Gast)


Lesenswert?

Hast du schon mal ausprobiert, ob das GNU splint bei deinem Beispiel 
eine Warnung ausgibt?

von Dirk B. (dirkb2)


Lesenswert?

Müller schrieb:
> Dazu noch eine Frage, warum "programmiert" man nicht einen Compiler der
> sowas standardmäßig prüft in C? Zumindestens bei so offentsichtlichen
> Sachen, wie in meinen zweiten Snipsel?

Wenn der Index aus einer Variablen kommt oder der Zugriff in einer 
Funktion stattfindet, geht das alles nicht mehr.

Aber es gibt ja "C"-Compiler die das machen. Nennen sich dann 
C++-Compiler und der Datentyp ist Vector.

von Hosenmatz (Gast)


Lesenswert?

Müller schrieb:
> Hallo zusammen,
>
> [...]
>
> Wenn man Speicher dynamisch reserviert, wird ja auch nur soviel
> reserviert, wie ich gerne hätte.

Das trifft so nicht grundsätzlich zu. Tatsächlich gibt es 
Implementierungen die auch Speicher, der mit malloc allokiert wird, in 
Blöcken reservieren.

> Der Code Snipsel stammte von mir, die Musterlösung müsste ich nochmal in
> meinen Unterlagen nachschauen.

Hinweis: Das heisst: "Schnippsel" und kommt von "schneiden".

> Dazu noch eine Frage, warum "programmiert" man nicht einen Compiler der
> sowas standardmäßig prüft in C? Zumindestens bei so offentsichtlichen
> Sachen, wie in meinen zweiten Snipsel?

Es kommt halt darauf an, was man unter einem Compiler versteht. Der 
primäre Zweck ist die "Übersetzung", nicht die Fehlerprüfung. Die Grenze 
ist allerdings oft nicht ganz scharf. Sie verläuft aber ungefähr dort, 
wo der Compiler eine Information über den Code "ohnehin" hat, d.h. wenn 
er zu ihrer Ermittlung keine weiteren Analysen machen muss. Ein Beispiel 
dafür sind Typinformationen. An sich bräuchte der Compiler dafür nur 
Code erzeugen, der eben zu dem angegebenen Typ passt. Da er aber bei 
Parametern den Typ des übergebenen Wertes weiß und den Typ, den die 
Funktion erwartet, vergleicht er die beiden. Er muss das im Falle von 
impliziten casts ohnehin tun.
Es sei zugegeben, dass Dein Beispiel relativ einfach zu implementieren 
wäre. Das geht nur eben über den Zweck eines Compilers hinaus.

Wenn Du tatsächlich statische Codeanalysen durchführen willst, gibt es 
dafür Werkzeuge wie "Lint".

von Hosenmatz (Gast)


Lesenswert?

Natürlich muss es "Schnipsel" heissen. Ist das peinlich. :-)

von Müller (Gast)


Lesenswert?

Hallo zusammen,

Vielen Dank für die Antworten. Aber ich meine der GCC z.B. Hat doch für 
jeden "Scheiß" eine Compiler Option, warum dann nicht bei so 
offensichtlichen Sachen, sowas auch implementieren.

Mir ist schon bewusst, dass man das nicht komplett prüfen kann, Vorallem 
wenn etwas dynamisches im Spiel ist.

Aber wenn ich mir ansehe, dass (ok dass war auf einem MacBook von einem 
Kollegen) dass er sogar eine Warnung bei gets rausgibt, denke ich mir 
nur, warum so flegmatisch sein ;-)

Das mit dem Snipsel hab ich mir wohl aus SNIppet und schniPSEL gebildet, 
es lebe die Denglisierung ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Müller schrieb:
> Sowas wurde anstandslos kompiliert und ohne Fehler / Warnungen. Und
> seltsamerweise hat das auch noch funktioniert?!
>
> Habe ich irgendwas verpasst oder optimiert der Compiler sowas
> automatisch????

Wie bereits gesagt, es ist Undefined Behavior.

C99 §3.4.3  Terms, Definitions and Symbols: Undefined Behavior
1
Behavior, upon use of a nonportable or erroneous program construct or
2
of erroneous data, for which this International Standard imposes no
3
requirements.
4
5
Note: Possible undefined behavior ranges from ignoring the situation
6
completely with unpredictable results, to behaving during translation
7
or program execution in a documented manner characteristic of the
8
environment (with or without the issuance of a diagnostic message),
9
to terminating a translation or execution (with the issuance of a
10
diagnostic message).
11
12
Example: An example of undefined behavior is the behavior on integer
13
overflow.

> Bisher dachte ich immer das wäre ein Buffer Overflow und muss
> aufjedenfall verhindert und abgefangen werden.

Falsch gedacht :-)

> Hat jemand eine Idee?

Das Konzept ist "Garbage in, garbage out": Müll rein, Müll raus.  In 
C(++) ist der Anwender für die Integrität und Konsistenz der Daten 
verantwortlich.

Das ermöglicht schnelle Programme für die Leute, die korrekte Programme 
schreiben auf Kosten der wenigen, die inkorrekte Programme schreiben.

Alternative wäre, ALLE mit einem Overhead zu bestrafen, der nötig wäre 
wenn versucht würde, die Konsistenz zur Laufzeit überprüfen zu wollen.

Beispiel:
1
int get_int (int *p)
2
{
3
    return *p;
4
}

Wie willst du überprüfen, ob p in einen gültigen Speicherbereich zeigt, 
ob das Alignment stimmt (was vom Speicherbereich abhängen kann), die 
Zugriffsrechte, ob da wirklich ein int (oder was kompatibles) 
gespeichert ist, usw.?

Es gibt zwar Tools wie ubsan, asan, valgrind etc. die dabei helfen, zur 
Entwicklungszeit Fehler aufzudecken, aber das ist weder ein Nachweis der 
Korrektheit, noch würde man den Overhead im Endprodukt tolerieren.

> Nun danach hab ich mich damit nochmal beschäftigt und so Späßchen
> probiert:
1
#include <stdio.h>
2
3
void func (void)
4
{
5
    char array[10];
6
    array[14] = 'A';
7
    printf ("%c", array[14]);
8
}

Ein avr-gcc v5 macht daraus
1
func:
2
  ldi r24,lo8(65)
3
  ldi r25,0
4
  rjmp putchar

IIRC werden Warnungen für -Warray-bounds relativ spät in der 
Compilierung ausgegeben.  Grund ist, dass Indices fast nie zur 
Compilezeit bekannt sind und durch Optimierung mehr potentielle Stellen 
gefunden werden können.

Warum im Beispiel keine Warnung ausgegeben wird, da musst du nen 
GCC-Entwickler fragen...  Ohne Optimierung wird jedenfalls auch keine 
Warnung ausgegeben obwohl außerhalb von array[] zugegriffen wird.

von Hosenmatz (Gast)


Lesenswert?

Müller schrieb:
> Hallo zusammen,
>
> Vielen Dank für die Antworten. Aber ich meine der GCC z.B. Hat doch für
> jeden "Scheiß" eine Compiler Option, warum dann nicht bei so
> offensichtlichen Sachen, sowas auch implementieren.

Das habe ich Dir beantwortet. Was genau hast Du daran nicht verstanden?
Du verlangst ja auch keinen Dosenöffner im PKW nur weil Du Dir mal aufm 
Rastplatz Ravioli warm machen möchtest. Fehlersuche ist eben keine 
Aufgabe eines Compilers.

> Mir ist schon bewusst, dass man das nicht komplett prüfen kann, Vorallem
> wenn etwas dynamisches im Spiel ist.

Darüber habe ich keine Aussage gemacht. Ich habe vielmehr verdeutlichen 
wollen, dass der Compiler gewisse Fehler meldet, weil er die dazu 
relevante Information ohnehin zur Codeerzeugung benötigt. Bei einem 
Arrayzugriff braucht er zur Codeerzeugung nur die Startadresse und einen 
Offset. Wie groß der Offset ist, d.h. ob effektiv diesseits der Größe 
zugreift, ist für den erzeugten Code irrelevant. Das Prinzip ist: 
"Soviel wie nötig" und nicht: "Alles was denkbar ist". In der Technik 
ohnehin die generelle Maxime. Das letztere ist nur eine 
Marketing-Masche.

> Aber wenn ich mir ansehe, dass (ok dass war auf einem MacBook von einem
> Kollegen) dass er sogar eine Warnung bei gets rausgibt, denke ich mir
> nur, warum so flegmatisch sein ;-)

Was ist das für eine Warnung und bei welchem Code genau? So kann ich 
dazu nichts sagen und weiß auch nicht, ob der Fall vergleichbar ist.

> Das mit dem Snipsel hab ich mir wohl aus SNIppet und schniPSEL gebildet,
> es lebe die Denglisierung ;-)

Tot wäre sie mir lieber. :-)

von Dirk B. (dirkb2)


Lesenswert?

Müller schrieb:
> Aber wenn ich mir ansehe, dass (ok dass war auf einem MacBook von einem
> Kollegen) dass er sogar eine Warnung bei gets rausgibt, denke ich mir
> nur, warum so flegmatisch sein ;-)

Das ist doch etwas anderes.
Das eine ist eine Warnung vor einer (abgekündigten) Funktion,
beim Anderen muss der Code analysiert werden.

von Noch einer (Gast)


Lesenswert?

>warum dann nicht bei so
>offensichtlichen Sachen, sowas auch implementieren

Da hilft ein Blick in die Geschichtsbücher. Kernighan & Ritchie wollten 
einen Compiler der alle Assemblertricks akzeptiert. Warnungen fanden die 
überflüssig.

Später schrieben andere Leute zusätzliche Tools, die Warnungen für 
gefährliche Konstruktionen ausgaben.

Heute sind die meisten C-Programmierer der Meinung, der Compiler soll 
vor allen Dingen schnell sein. Und schnellen, kompakten Code erzeugen. 
Nett, wenn er nebenbei noch ein paar Warnungen ausgeben kann. Das darf 
aber den Compiler nicht langsamer machen.

Wer Warnungen haben will, benutzt zusätzlich zum Compiler noch weitere 
Tools. Als wir Makefiles noch selbst schreiben konnten, hatten wir da 2 
Targets eingetragen. Eines, was schnell compiliert. Und eines, was alle 
Warnungen ausgab.

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
> Warum im Beispiel keine Warnung ausgegeben wird, da musst du nen
> GCC-Entwickler fragen...  Ohne Optimierung wird jedenfalls auch keine
> Warnung ausgegeben obwohl außerhalb von array[] zugegriffen wird.

Interessanterweise wird gewarnt, wenn man das Array global macht und die 
Optimierungen mindestens auf Level 2 stellt.

von Eric B. (beric)


Lesenswert?

Müller schrieb:
> Bei der Aufgaben Besprechung fiel mir auf, dass keinerlei Abfrage drinne
> war, in der man nach rechtzeitig ein beschreiben eines Arrays außerhalb
> seiner Größe verhinderte.

> Meine Lösung sah so aus:
    ....
>             // Zeichen verarbeiten
>             else if(key != 8 && x <= size-2)
    ....

Hier hast du doch deine Abfrage drinne?

: Bearbeitet durch User
von Hans-Georg L. (h-g-l)


Lesenswert?

Was immer wieder gerne vergessen wird .. der Index von Arrays in C ist 
signed und nicht unsigned.

von Mark B. (markbrandis)


Lesenswert?

Hans-Georg L. schrieb:
> Was immer wieder gerne vergessen wird .. der Index von Arrays in C ist
> signed und nicht unsigned.

Ein möglicherweise negativer Index? Welchen Sinn mag dies denn nun 
haben?

Ich habe das so gelernt, dass das erste Element eines Arrays in C den 
Index 0 hat. Und vor dem ersten Element gibt es kein anderes.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Hans-Georg L. schrieb:
> Was immer wieder gerne vergessen wird .. der Index von Arrays in C ist
> signed und nicht unsigned.

Stimmt, der AVR-GCC läßt kein Array oder Struct >32767Byte zu, obwohl 
man 64kB RAM adressieren kann. Man muß mehre Arrays anlegen.
Schon recht merkwürdig, diese unnötige Einschränkung.

von Peter II (Gast)


Lesenswert?

Mark B. schrieb:
> Ich habe das so gelernt, dass das erste Element eines Arrays in C den
> Index 0 hat. Und vor dem ersten Element gibt es kein anderes.
1
char tmp[10];
2
char* tmp2 = &tmp[5];
3
tmp2[-1] = 'a';

von Peter II (Gast)


Lesenswert?

Le X. schrieb im Beitrag #4614496:
> Was möchte uns wohl der Peter mit diesem wortlos hingerotzten Codefetzen
> sagen?
> Dass der Compiler das schluckt? Geschenkt.
> Mark Brandis ging es eher um den Sinn hinter dieser Regel

das es sinnvoll nutzbar ist ein negativer index.

man darf auch von einen Pointer etwas subtrahieren.
1
char* p;
2
char* p2 = p - 5;

nur weil es bei einem Array keinen offensichtlichen Grund gibt, ist es 
für Pointer immer noch notwendig.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Hans-Georg L. schrieb:
>> Was immer wieder gerne vergessen wird .. der Index von Arrays in C ist
>> signed und nicht unsigned.
>
> Stimmt, der AVR-GCC läßt kein Array oder Struct >32767Byte zu, obwohl
> man 64kB RAM adressieren kann. Man muß mehre Arrays anlegen.
> Schon recht merkwürdig, diese unnötige Einschränkung.

Ansonsten wäre es nicht mehr möglich, Diferenzen aus Zeigern zu bilden, 
denn diese sollen in einen ptrdiff_t passen, der eben nur 16 Bits groß 
ist und somit nur Differenzen von -32768...32767 aufnehmen kann.

Du kannst dir natürlich auch ein eigenes ABI definieren und 
implementieren wenn das momentane ABI zu restriktive oder zu "klein" 
ist.

: Bearbeitet durch User
von Hans-Georg L. (h-g-l)


Lesenswert?

Mark B. schrieb:
> Hans-Georg L. schrieb:
>> Was immer wieder gerne vergessen wird .. der Index von Arrays in C ist
>> signed und nicht unsigned.
>
> Ein möglicherweise negativer Index? Welchen Sinn mag dies denn nun
> haben?
>

Das ist durchaus so gewollt und wurde immer wieder gerne für 
Speicherverwaltung benutzt indem man zu dem angeforderten Speicherplatz 
noch einen Infoblock zusätzlich belegt und einen Pointer auf den 
Speicherbereich hinter dem Infoblock zurückgegeben hat.

Dann kann die Speicherverwaltung mit einem negativen index auf den 
Infoblock zugreifen und der Benutzer mit positiven Index auf die Daten.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.