[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[OT] Warum kein Speicherzugriffsfehler



Hallo!

Ich weiß, es ist off topic, aber ich bin jetzt grad so neugierig, dass ich 
trotzdem mal fragen möchte. Ausgehend von der Diskussion zum 
Speicherverbrauch von tab-basierten Konsolen bin ich bei einem 
Galileobuch gelandet, wo auch ein Absatz zum virtuellen Speicher drin ist 
und Speicher anfordern drin ist[1].

Da ist nettes Beispiel zum Speicher anfordern drin und auch ne Erklärung, 
wie es zu einem Speicherzugriffsfehler kommen kann.

Nun wollte ich das mal ausprobieren:

martin@shambala> cat zugriffsfehler.c
#include <stdlib.h>
#include <stdio.h>

int main()
{
  char* puffer;                // Variable deklarieren
  puffer = malloc(4096);       // 4 KB = 4096 Bytes
                               // anfordern

  // Nun kann der Speicherbereich benutzt werden

  printf("4 KB Addressraum belegt ab: %ld\n", puffer);

  free(puffer);                // Speicherbereich
                               // wieder freigeben

  // Jeder Zugriff, der nach dem Freigeben auf den
  // Speicherbereich der Variable 'puffer'
  // erfolgt, führt zu einem Speicherzugriffsfehler

  printf("Zeiger auf den Speicher nach dem free(): %ld\n", puffer);

  printf("Und Speicherzugriffsfehler ;-)\n");

  int i;

  for (i==0; i<1; i++) {
    puffer[i] = 0;
  }

  return 0;                    // Programm beenden
}

Gestartet ergibt dies wie gewünscht:

martin@shambala> gcc zugriffsfehler.c
martin@shambala> ./a.out                                                             
~/Computer/Programmieren/C/speicherverwaltung
4 KB Addressraum belegt ab: 134520840
Zeiger auf den Speicher nach dem free(): 134520840
Und Speicherzugriffsfehler ;-)
zsh: segmentation fault  ./a.out


Zuerst probierte ich jedoch die naive Variante ohne for-Schleife:

martin@shambala> cat warum-kein-zugriffsfehler.c
#include <stdlib.h>
#include <stdio.h>

int main()
{
  char* puffer;                // Variable deklarieren
  puffer = malloc(4096);       // 4 KB = 4096 Bytes
                               // anfordern

  // Nun kann der Speicherbereich benutzt werden

  printf("4 KB Addressraum belegt ab: %ld\n", puffer);

  free(puffer);                // Speicherbereich
                               // wieder freigeben

  // Jeder Zugriff, der nach dem Freigeben auf den
  // Speicherbereich der Variable 'puffer'
  // erfolgt, führt zu einem Speicherzugriffsfehler

  printf("Zeiger auf den Speicher nach dem free(): %ld\n", puffer);

  printf("Und Speicherzugriffsfehler ;-) oder doch nicht?\n");

  puffer[40]=1;

  puffer[45]=232;
  puffer[46]=232;
  puffer[47]=232;
  puffer[48]=232;
  puffer[49]=232;
  puffer[50]=232;
  puffer[51]=232;
  puffer[52]=232;

  return 0;                    // Programm beenden
}

Und die sollte doch eigentlich auch gehen! Doch hier bleibt der gewünschte 
Effekt aus:

martin@shambala> gcc -O0 warum-kein-zugriffsfehler.c
martin@shambala> ./a.out                                                             
~/Computer/Programmieren/C/speicherverwaltung
4 KB Addressraum belegt ab: 134520840
Zeiger auf den Speicher nach dem free(): 134520840
Und Speicherzugriffsfehler ;-) oder doch nicht?


Warum interessiert sich der Linux-Kernel nicht für die illegalen 
Speicherzugriffe des zweiten Programms? 


martin@shambala> cat /proc/version
Linux version 2.6.24.2-tp42-toi-3.0-rc5 (martin@shambala) (gcc version 
4.2.3 20080114 (prerelease) (Debian 4.2.2-7)) #1 PREEMPT Wed Feb 13 
00:18:13 CET 2008


[1] Virtueller Speicher: 
http://www.galileocomputing.de/openbook/linux/linux_kap01_002.htm#mj02fce95f298e356b9ec54c17a8f92309

Ciao,
-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7


Reply to: