Błąd segmentacji: alokacja stosu w programie C w Ubuntu po buforowaniu> 4M
Oto mały program do zadania uczelni:
#include <unistd.h>
#ifndef BUFFERSIZE
#define BUFFERSIZE 1
#endif
main()
{
char buffer[BUFFERSIZE];
int i;
int j = BUFFERSIZE;
i = read(0, buffer, BUFFERSIZE);
while (i>0)
{
write(1, buffer, i);
i = read(0, buffer, BUFFERSIZE);
}
return 0;
}
Zamiast tego istnieje alternatywne użycie funkcji stdio.h fread i fwrite.
Dobrze. Obie wersje programu skompilowałem z 25 różnymi wartościami rozmiaru bufora: 1, 2, 4, ..., 2 ^ i z i = 0..30
Oto przykład, jak go kompiluję: gcc -DBUFFERSIZE = 8388608 prog_sys.c -o bin / psys.8M
Pytanie: W moim komputerze (Ubuntu Precise 64, więcej szczegółów na końcu) wszystkie wersje programu działają poprawnie: ./psys.1M <dane
(dane to mały plik z 3 liniami tekstu ascii.)
Problem polega na tym, że gdy rozmiar bufora wynosi 8 MB lub więcej. Obie wersje (za pomocą funkcji wywołania systemowego lub funkcji clib) ulegają awarii z tymi rozmiarami buforów (błąd segmentacji).
Przetestowałem wiele rzeczy. Pierwsza wersja kodu wyglądała następująco: (...) main () {bufor bufora [BUFFERSIZE]; int i;
i = read(0, buffer, BUFFERSIZE);
(...)
To zawiesza się, gdy wywołam funkcję odczytu. Ale z tymi wersjami:
main()
{
char buffer[BUFFERSIZE]; // SEGMENTATION FAULT HERE
int i;
int j = BUFFERSIZE;
i = read(0, buffer, BUFFERSIZE);
main()
{
int j = BUFFERSIZE; // SEGMENTATION FAULT HERE
char buffer[BUFFERSIZE];
int i;
i = read(0, buffer, BUFFERSIZE);
Oba z nich ulegają awarii (SEGFAULT) w pierwszej linii głównej. Jeśli jednak przeniosę bufor z głównego do globalnego zakresu (a więc do alokacji w stercie zamiast do stosu), to działa dobrze:
char buffer[BUFFERSIZE]; //NOW GLOBAL AND WORKING FINE
main()
{
int j = BUFFERSIZE;
int i;
i = read(0, buffer, BUFFERSIZE);
Używam Ubuntu Precise 12.04 64 bitów i Intel i5 M 480 pierwszej generacji.
#uname -a
Linux hostname 3.2.0-34-generic #53-Ubuntu SMP Thu Nov 15 10:48:16 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
Nie znam ograniczeń systemu operacyjnego dotyczących stosu. Czy jest jakiś sposób na przydzielenie dużych danych w stosie, nawet jeśli nie jest to dobry wybór?