2012-02-11 21 views
7

Đôi khi chúng ta đặt một số bản in debug trong mã của chúng tôi cáchCó an toàn để vô hiệu hóa việc lưu vào bộ đệm với stdout và stderr không?

printf("successfully reached at debug-point 1\n"); 

some code is here 

printf("successfully reached at debug-point 2"); 

Here segmantaion fault occur due to some reason 

này Bây giờ trong tình trạng này chỉ debug-point1 sẽ in trên stdio debug điểm 2 in được viết để stdio đệm nhưng nó không đỏ mặt vì nó didnt được \n vì vậy chúng tôi nghĩ rằng tai nạn xảy ra sau khi debug-point1

đến hơn đến từ này nếu tôi vô hiệu hóa tùy chọn đệm với stdio và dòng stderr như cách này

setvbuf(stdout, NULL, _IONBF, 0); 
setvbuf(stderr, NULL, _IONBF, 0); 

sau đó là thế này an toàn để làm điều này?

lý do tại sao tất cả các luồng là theo mặc định dòng đệm?

Edit:

Thông thường những gì là kích thước của ví dụ bằng cách đệm mặc định phân bổ cho bất kỳ dòng tập tin? tôi nghĩ rằng os của nó phụ thuộc. tôi muốn biết về Linux?

Trả lời

3

lý do tại sao tất cả các dòng là bởi dòng mặc định đệm

Họ đang đệm cho lý do hiệu suất. Thư viện cố gắng hết sức để tránh thực hiện cuộc gọi hệ thống vì mất nhiều thời gian. Và không phải tất cả chúng đều được đệm theo mặc định. Ví dụ: stderrthường là không bị chặn và stdout chỉ được xếp vào bộ đệm khi nó đề cập đến một tty.

thì việc này có an toàn không?

Bạn có thể tắt tính năng đệm nhưng tôi phải nói đó không phải là kỹ thuật gỡ lỗi tốt nhất.

2

Uh, tốt. Bạn đã sai. Chính vì lý do này, stderrkhông được đệm theo mặc định.

EDIT: Ngoài ra, như một gợi ý chung, hãy thử sử dụng điểm ngắt trình gỡ lỗi thay vì printf s. Làm cho cuộc sống dễ dàng hơn nhiều.

6

Một cách có thể là có một cờ toàn cầu bool dodebug và xác định macro như ví dụ:

#ifdef NDEBUG 
#define debugprintf(Fmt,...) do{} while(0) 
#else 
#define debugprintf(Fmt,...) do {if (dodebug) {     \ 
    printf("%s:%d " Fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ 
    fflush(stdout); }} while(0) 
#endif 

Sau đó bên trong mã của bạn, có một số

debugprintf("here i=%d", i); 

Tất nhiên, bạn có thể, trong vĩ mô trên, làm fprintf thay vì ... Chú ý fflush và xuống dòng nối vào định dạng.

Có thể tránh việc tắt đệm vì lý do hiệu suất.

2

Điều này là "an toàn" theo một nghĩa nào đó và không an toàn ở một cách khác.Nó là không an toàn để thêm debug printfs, và cho cùng một lý do không an toàn để thêm mã để sửa đổi bộ đệm stdio, theo nghĩa là nó là một cơn ác mộng bảo trì. Những gì bạn đang làm không phải là một kỹ thuật gỡ lỗi tốt. Nếu chương trình của bạn nhận được một segfault, bạn chỉ cần kiểm tra các dump cốt lõi để xem những gì đã xảy ra. Nếu điều đó không đầy đủ, hãy chạy chương trình trong trình gỡ lỗi và thực hiện bước này để thực hiện hành động. Điều này nghe có vẻ khó, nhưng nó thực sự rất đơn giản và là một kỹ năng quan trọng cần có. Đây là mẫu:

 
$ gcc -o segfault -g segfault.c # compile with -g to get debugging symbols 
$ ulimit -c unlimited    # allow core dumps to be written 
$ ./segfault      # run the program 
Segmentation fault (core dumped) 
$ gdb -q segfault /cores/core.3632 # On linux, the core dump will exist in 
            # whatever directory was current for the 
            # process at the time it crashed. Usually 
            # this is the directory from which you ran 
            # the program. 
Reading symbols for shared libraries .. done 
Reading symbols for shared libraries . done 
Reading symbols for shared libraries .. done 
#0 0x0000000100000f3c in main() at segfault.c:5 
5    return *x;   <--- Oh, my, the segfault occured at line 5 
(gdb) print x      <--- And it's because the program dereferenced 
$1 = (int *) 0x0      ... a NULL pointer. 
2

Nếu chương trình của bạn viết nhiều đầu ra, việc tắt đệm có thể làm chậm hơn từ 10 đến 1000 lần. Điều này thường không mong muốn. Nếu mục tiêu của bạn chỉ là tính nhất quán của đầu ra khi gỡ lỗi, hãy thử thêm các cuộc gọi rõ ràng fflush nơi bạn muốn xóa đầu ra thay vì tắt đệm trên toàn cầu. Và tốt nhất là không viết mã bị lỗi ...