簡體   English   中英

打印到stderr時檢查fprintf時出錯

[英]Error checking fprintf when printing to stderr

根據文檔,fprintf可能會失敗,並會在失敗時返回負數。 顯然有很多情況下檢查這個值是有用的。

但是,我通常使用fprintf將錯誤消息打印到stderr。 我的代碼通常看起來像這樣:

rc = foo();
if(rc) {
  fprintf(stderr, "An error occured\n");
  //Sometimes stuff will need to be cleaned up here
  return 1;
}

在這些情況下,fprintf仍然可能失敗嗎? 如果是這樣,有什么方法可以用來以某種方式顯示錯誤消息,或者是否有更可靠的替代fprintf?

如果沒有,是否需要檢查fprintf以何種方式使用?

C標准說文件流stdin,stdout和stderr應該在某處連接,但它們當然沒有指定位置。 運行重定向的程序是完全可行的:

some_program_of_yours >/dev/null 2>&1 </dev/null

你的寫作會成功 - 但信息不會隨處可見。 運行程序的更殘酷的方法是:

some_program_of_yours >&- 2>&- </dev/null

這一次,它運行時沒有stdout和stderr的打開文件流 - 違反了標准。 它仍然是從示例中的/ dev / null讀取,這意味着它沒有從stdin獲得任何有用的數據輸入。

許多程序都不願意檢查標准I / O通道是否打開。 許多程序都不願意檢查錯誤消息是否已成功寫入。 設計Tim Postwhitey04作為大綱的合適后備並不總是值得的。 如果運行ls命令並禁止其輸出,它將只執行它所能做的並以非零狀態退出:

$ ls; echo $?
gls
0
$ ls >&- 2>&-; echo $?
2
$

(經過測試的RHEL Linux。)確實沒有必要做更多。 另一方面,如果你的程序應該在后台運行並寫入日志文件,它可能不會寫很多東西到stderr,除非它無法打開日志文件(或在日志文件上發現錯誤) 。

請注意,如果您回到syslog(3) (或POSIX ),您無法知道您的通話是否“成功”; syslog函數都不返回任何狀態信息。 你只需要假設它們是成功的。 因此,這是你最后的選擇。

通常情況下,您可以使用某種日志系統來(嘗試)為您處理此問題,或者您需要在代碼的每個區域復制該邏輯,以打印到標准錯誤並退出。

你有一些選擇:

  • 如果fprintf失敗,請嘗試syslog。
  • 如果兩者都失敗,請嘗試創建一個'crash。{pid} .log'文件,其中包含您在錯誤報告中需要的信息。 啟動時檢查這些文件是否存在,因為它們可以告訴程序先前它已崩潰。
  • 讓網絡連接用戶檢查允許程序提交錯誤報告的配置選項。

順便說一下,當fprintf系列函數不工作時, open() read()write()是好朋友。

正如whitey04所說 ,有時你只需要放棄並盡力不讓煙花消失。 但是,請嘗試將這種邏輯隔離到一個小型庫中。

例如:

    best_effort_logger(LOG_CRIT, "Heap corruption likely, bailing out!");

比了一系列更清潔的if else else if每一個地方的東西可能出問題。

你可以將錯誤放在stdout或其他地方......在某些時候你只需要給出錯誤報告,然后放棄。

關鍵是你的應用程序“優雅地”處理它(例如,操作系統不必因為壞而殺死它,它會告訴你為什么退出它[如果它可以])。

是的,當然fprintfstderr可能會失敗。 例如, stderr可能是普通文件,磁盤可能空間不足,或者它可能是讀取器關閉的管道等。

是否應該檢查操作是否失敗在很大程度上取決於您是否可以通過檢查來實現更好的程序行為。 在你的情況下,你可以做的唯一可以想象的事情是打印錯誤信息失敗是嘗試打印另一個(幾乎肯定也會失敗)或退出程序(這可能比沒有報告錯誤更糟糕,但也許不總是)。

一些真正想要記錄錯誤消息的程序將在程序啟動時設置備用堆棧以保留一定量的內存(請參閱信號處理程序(通常為SIGSEGV )可用於報告錯誤的sigaltstack(2) 。記錄你的錯誤的重要性,你可以調查使用備用堆棧預先分配一些內存。它可能不值得:)但有時你會給出一些事情的暗示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM