簡體   English   中英

在 function 中調用 char* var (假設全局訪問) = fgets(..) 后,在從 main 調用 function 后 var 中的值意外更改

[英]After invoking char* var (assume global access) = fgets(..) inside a function, the value inside var changes unexpectedly after function call from main

[編輯:顯然從 fgets 獲得的返回值只是正在使用的 char 緩沖區 [SIZE] 的地址,所以在我的情況下這是有道理的,因為我在本地聲明了它(因此,塊范圍).. PS:感謝所有幫助!]

我只是傾向於一旦編譯器執行完調用 fgets 的 function,fgets 存儲的數據就不會保持不變。

這背后的原因是什么? fgets 的返回數據是否有生命周期之類的? 如果是這樣,他們甚至是如何編寫諸如 fgets 之類的 function 的? 可以跟蹤用戶調用 scope 的東西嗎?

這是代碼:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define SIZE 10

void input_string (char** pptr_one, char** pptr_two)
{
    char buffer[SIZE];
    printf("\nInput: ");
    char* x = fgets(buffer, SIZE, stdin);
    
    //Copying the original fgets result address:
    *pptr_one = x;
    //Copying its contents to another variable:
    *pptr_two = malloc(SIZE);
    strcpy(*pptr_two, x);
}

int main (int argc, char **argv)
{
    char* ptr_one;
    char* ptr_two;
    input_string(&ptr_one, &ptr_two);

    printf("\nptr_one is pointing to: <%s>\n", ptr_one);
    printf("ptr_two is pointing to: <%s>\n", ptr_two);

    return 0;
}

您的緩沖區char buffer[SIZE]具有自動存儲持續時間。

這意味着在 function input_string()返回后,與buffer關聯的 memory 將被釋放,並且buffer將不復存在,因為它是一個局部變量。

解決方案:

您可以使用malloc()buffer分配 memory :

  • char *buffer = malloc(sizeof(char) * SIZE)

或者您可以將buffer聲明為static

  • static char buffer[SIZE];

您(間接)將*pptr_one設置為buffer的地址,當input_string結束時該地址停止存在。

fgets沒有什么特別之處; 它只是在成功時返回它的第一個參數,在這種情況下是buffer 之后, x*pptr_one都指向 function 本地的同一塊 memory。

參考

void input_string (char** pptr_one, char** pptr_two)
{
    char buffer[SIZE];
    printf("\nInput: ");
    char* x = fgets(buffer, SIZE, stdin);
    // missing test for NULL return from fgets()

    /*** DO NOT DO THIS.
     * DO NOT TAKE THE ADDRESS OF A LOCAL VARIABLE FOR USE AFTER FUNCTION EXITS!
     * When successful, fgets will return the address of 'buffer' so x points to buffer.
    //Copying the original fgets result address:
    *pptr_one = x;
    *****/

    //Copying its contents to another variable:
    *pptr_two = malloc(SIZE);
    // should check that malloc succeeded
    strcpy(*pptr_two, x);
    // Aren't you glad that fgets() guarantees buffer will be a null terminated string?

    // Be sure caller free's the allocated piece of heap storage!
}

或者,如果您想使用該信息,請制作緩沖區 static...

    static char buffer[SIZE];
    printf("\nInput: ");

如果使用 memory 的 static 塊,請勿釋放地址。

查看 OP,您寫道:“我剛剛了解到 fgets 存儲的數據doesn't stay the same once the... [execution of] the function in which fgets is being invoked.

所有數據都有一個持續時間。 有些是磁盤上文件的持續時間,有些是程序執行的整個持續時間,有些是 function 調用的短暫持續時間。

input_string()結束並返回到它的調用 function ('main()') 時,你的“緩沖區”消失了。 掛在數據上的另一種方法是在main()中定義它並將緩沖區及其長度傳遞給input_string()

void input_string( char *buf, size_t len ) {
    fgets(buffer, len, stdin);
}

int main() {
    char buffer[ SIZE ];
    input_string( buffer, sizeof buffer );
    printf( "Got '%s' from stdin\n", buffer );
}

上面, input_string()完成了,但數據仍然可用。

暫無
暫無

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

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