2012-04-20 8 views
5

Tenía curiosidad acerca de qué tipo de tamaños de buffer write() y read() podrían manejar en Linux/OSX/FreeBSD, así que comencé a jugar con programas tontos como lo siguiente:segfault en write() con ~ 8MB buffer (OSX, Linux)

#include <unistd.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/stat.h> 

int main(void) { 
    size_t s = 8*1024*1024 - 16*1024; 
    while(1) { 
     s += 1024; 
     int f = open("test.txt", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR); 
     char mem[s]; 
     size_t written = write(f, &mem[0], s); 
     close(f); 
     printf("(%ld) %lu\n", sizeof(size_t), written); 
    } 
    return 0; 
} 

Esto me permitió probar qué tan cerca de una "barrera de 8 MB" aparente que podría conseguir antes violación de segmento. En algún lugar alrededor de la marca de 8 MB, mi programa muere, aquí está un ejemplo de salida:

(8) 8373248 
(8) 8374272 
(8) 8375296 
(8) 8376320 
(8) 8377344 
(8) 8378368 
(8) 8379392 
(8) 8380416 
(8) 8381440 
(8) 8382464 
Segmentation fault: 11 

Ésta es la misma en OSX y Linux, sin embargo, mi FreeBSD máquina virtual no sólo es mucho más rápido en el funcionamiento de esta prueba, también puede seguir ¡para bastante maneras! Lo he probado con éxito hasta 511 MB, que es una cantidad ridícula de datos para escribir en una sola llamada.

¿Qué es lo que hace que write() llame segfault, y cómo puedo calcular la cantidad máxima que puedo escribir() en una sola llamada, sin hacer algo ridículo como lo estoy haciendo ahora mismo?

(Nota, los tres sistemas operativos son de 64 bits, OSX 10.7.3, Ubuntu 11.10, FreeBSD 9.0)

Respuesta

5

La culpano está dentro write(), es un desbordamiento de pila. Pruebe esto:

#include <stdlib.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/stat.h> 

int main(void) 
{ 
    void *mem; 
    size_t s = 512*1024*1024 - 16*1024; 
    while(1) 
    { 
     s += 1024; 
     int f = open("test.txt", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR); 
     mem = malloc(s); 
     size_t written = write(f, mem, s); 
     free(mem); 
     close(f); 
     printf("(%ld) %lu\n", sizeof(size_t), written); 
    } 
    return 0; 
} 
+0

* suspiro * Realmente debería haberme dado cuenta de eso. Lo pensé y luego olvidé de pensar antes de compilar. ¡Gracias! – staticfloat

+0

@staticfloat Traté de ver si podía * demostrar * que era un desbordamiento de pila usando 'strace' y' gdb' pero no pude - quizás alguien podría sugerir que un desbordamiento de pila puede ser definitivamente determinado como la causa de un culpa. – trojanfoe

+0

En caso de que te lo estés preguntando, eso realmente solucionó el problema. :) – staticfloat

Cuestiones relacionadas