簡體   English   中英

為什么errno,當POSIX函數通過返回-1或NULL指示錯誤條件時

[英]Why errno, when POSIX function indicate error condition by returning -1 or NULL

當其中一個UNIX系統函數發生錯誤時,通常會返回負值,並將整數errno設置為一個值,從而提供其他信息。 - UNIX環境中的高級編程,第1.7節

這看起來很奇怪:

  • 它引入了標准庫的不同編譯單元之間的耦合 - 錯誤狀態未在導致它們的模塊中定義。
  • 它引入了實現復雜性,因為errno需要是線程本地的。
  • 它引入了可用性復雜性,因為用戶需要檢查原始系統調用是否有錯誤,然后檢查errno哪個也是另一個函數調用。

為什么不在返回值中編碼錯誤狀態?

主要由於歷史原因。

請注意,實際上, errno今天不是普通的全局變量(在20世紀80年代就是這種情況)。 這是今天(C99,C11 ...)宏-通常是擴展到一些函數調用,或許__errno()和最近的C標准要求 errno是一個宏,見n1570第7.5節); 或者它可能會擴展到一些線程局部變量,甚至一些編譯器魔法。

errno希望成為多線程需求的宏,所以我猜這些標准發展到要求它成為一些宏

所以你應該#include <errno.h>並使用errno宏,就好像它是一個全局變量,但知道它實際上不是一個。

細節是特定於實現的。 查看C標准庫的源代碼,例如musl-libcerrno / __ errno_location.c中

  int *__errno_location(void)
  {
     return &__pthread_self()->errno_val;
  }

並在include / errno.h公共標題中:

 int *__errno_location(void);
 #define errno (*__errno_location())

和GNU libc有一些非常相似的東西

BTW一些​​系統函數不返回整數(例如mmap ),並且一些POSIX函數不指示錯誤通過errno ,例如dlopen (參見dlerror )。 因此,在某些標准中很難保證每個錯誤都可以由返回值指示。

我會引用Linus Torvalds的話。

“錯誤號”在UNIX那幾個非常糟糕愚蠢的一個。 Linux修復了它,並沒有在內部使用它,也永遠不會。 太糟糕了,用戶空間必須修復返回內核所做的正確錯誤代碼,並將其轉換為“errno”愚蠢以實現向后兼容性。

[...]

“errno”是那些根本不應該存在的破碎事物之一。 原來的UNIX是錯的,現在錯了。

[...]

Linux返回負錯誤號的方法要好得多。 它本質上是線程安全的,並沒有性能缺點。 當然,它確實依賴於擁有足夠的結果域,您可以始終將錯誤返回與良好的返回分開,但在實踐中對所有系統調用都是如此。

暫無
暫無

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

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