簡體   English   中英

使用getpwnam()時靜態分配的變量

[英]statically allocated variable when using getpwnam()

我正在研究系統編程。

有很多函數返回靜態分配的變量。

其中之一是getpwnam()

因此,在本書示例中,我正在閱讀:

printf("%ld %ld\\n", (long)(getpwnam("tsr")->pw_uid), (long)(getpwnam("avr")->pw_uid));

兩者都返回相同的uid,盡管在/etc/passwd ,它們的uid不同。 並且,解釋原因。

這是問題。

但是,我認為這是由於靜態分配的變量。 但是,結果是輸出是不同的(例如,類似於3001、3005)。

為什么輸出不同?

根據這本書,輸出應該是相同的。

並且,是否在函數中返回靜態分配的變量(如局部變量(自動變量))?

例如:

char* func(const char** name)
{
    char str[256];
    strcpy(str,name);
    return str;
}

編譯器可以自由調用getpwname ,然后以其喜歡的任何順序訪問pw_uid字段。

例如,它可能生成如下代碼:

struct passwd *pw1 = getpwname("tsr");
struct passwd *pw2 = getpwname("avr");
long uid1 = pw1->pw_uid;
long uid2 = pw2->pw_uid;
printf("%ld %ld\n", uid1, uid2);

它將打印相同的數字,因為對getpwname兩次調用getpwname返回指向相同static變量的指針,而第二個調用將getpwname一個指針編寫的內容,然后我們才有機會獲取所需的數據。 這是本書所期望的事情。

另一方面,編譯器也可能會選擇執行類似

struct passwd *pw1 = getpwname("tsr");
long uid1 = pw1->pw_uid;
struct passwd *pw2 = getpwname("avr");
long uid2 = pw2->pw_uid;
printf("%ld %ld\n", uid1, uid2);

在這種情況下,我們需要的信息(UID)在第二次調用getpwname之前被保存在另一個變量中。

需要強調的是,兩種生成代碼的方式都對編譯器合法(從技術上講,函數的參數之間沒有序列點,因此副作用可能以任何順序發生),因此您應像在第二個示例,以確保它將始終正常運行。

(順便說一句,通常最好通過支持這些函數的可重入版本來避免這些意外情況-例如, getpwnam_r不會返回指向在下一次調用時被覆蓋的靜態數據的指針,而是填充您提供的結構)

並且,是否在函數中返回靜態分配的變量(如局部變量(自動變量))?

不完全是; 返回指向局部變量的指針是非法的,因為當函數返回時,該變量“在邏輯上不復存在”,因此,您將返回一個不再擁有的內存的指針; 實際上,無論何時重用其在堆棧中的位置(例如,在下一個函數調用時或在函數的后面),此類內存都會被不相關的數據意外地覆蓋。

相反,返回指向靜態分配的變量的指針(即,全局或static局部變量-實際上實際上是一個偽裝的全局變量)是合法的-該內存是您的,並且不會隨處可見-但由於該內存在對該調用的所有調用之間共享函數,勢必在下一次調用該函數時被覆蓋。 這使得編寫在嵌套調用中使用該功能的代碼變得復雜,並且線程安全或異步安全(如:在信號處理程序中可用)的代碼完全不可能。

根據文檔, getpwnam返回指向靜態存儲的指針,隨后的對getpwentgetpwnamgetpwuid調用可能會覆蓋它。 這就是為什么您看到不一致的結果。 作為建議,您可以使用這些函數的reentrent變體getpwnam_rgetpwuid_r ,將信息返回給用戶提供的緩沖區,而不是靜態緩沖區。

並且,是否在函數中返回靜態分配的變量(如局部變量(自動變量))?

不同之處在於,靜態存儲的數據只初始化一次並存在於程序的整個生命周期中,而這些自動變量僅存在於定義的塊中。 因此,在您的示例中,當函數func返回時, str數組不再存在,並且使用它是未定義的行為。 如果是靜態的,則可以。

char* func(const char** name)
{
    static char str[256];
    strcpy(str,name);
    return str;
}

但是請記住,使用靜態數據通常會導致該函數無法重入。

暫無
暫無

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

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