2012-04-20 23 views
5

我很好奇Linux/OSX/FreeBSD上write()和read()可以處理什麼樣的緩衝區大小,所以我開始玩類似愚蠢的程序以下內容:帶有〜8MB緩衝區的寫入()上的段錯誤(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; 
} 

這讓我測試如何接近看似「8MB屏障」我以前段錯誤得到。地方約8MB的標誌,我的節目死了,這裏是一個例子輸出:

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

這是OSX和Linux一樣的,但是我的FreeBSD VM不僅在運行此測試快得多,它也可以去相當多的方式!我已經成功測試了它高達511MB,這在一次調用中寫入的數據量非常大。

這是什麼使得write()調用segfault,以及如何在一次調用中找出我可能寫入的最大數量(),而不是像我現在正在做的那樣做一些荒謬的事情?

(注意,這三個操作系統是64位,OSX 10.7.3的,Ubuntu 11.10,FreeBSD的9.0)

回答

5

故障不在範圍write(),這是一個堆棧溢出。試試這個:

#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

*嘆*我真的應該意識到這一點。我考慮了一下,然後在編譯之前立即忘了考慮。謝謝! – staticfloat 2012-04-20 08:36:00

+0

@staticfloat我試着看看我能否*證明*這是一個使用'strace'和'gdb'的堆棧溢出,但我不能 - 可能有人可能會建議如何確定堆棧溢出可能是導致故障。 – trojanfoe 2012-04-20 08:44:32

+0

如果你想知道,那實際上確實解決了這個問題。 :) – staticfloat 2012-04-23 04:37:02