簡體   English   中英

沒有malloc的指針

[英]pointer without a malloc

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main(){
        struct stat *something;
        stat("/etc/profile", something);
        printf("%d\n", something->st_gid);
        free(something);
        return 0;
}
$ ./a.out
Segmentation fault

從這篇文章中學 ,我需要使用malloc分配內存,因此我將其更改為如下所示,並且可以正常工作:

-       struct stat *something;
+       struct stat *something = malloc(sizeof(struct stat));

在先前但相關的練習中,我沒有使用malloc,並且它起作用了。 我搞不清楚了! 為什么在下面的行“ * struct dirent b; ”中不需要malloc?

或者,換句話說,我們如何才能知道有效負載太多並使用malloc?

#include <stdio.h>
#include <dirent.h>

int main(int argc, char *argv[]){

        if (argc != 2){
                printf("Error. Syntax: ls <somefolder> \n");
                return 1;
        }
        DIR *a = opendir(argv[1]) ;
        if (a == NULL){
                printf("error. cannot open %s\n", argv[1]);
                return 1;
        }

        // - malloc question about this very next line
        struct dirent *b; 
        while (( b = readdir(a)) != NULL){
                printf("%s %lu\n", b->d_name, b->d_ino);
        }

        int closing = closedir(a);
        printf("in closing, status is %d\n", closing);
        return 0;
}

C的新手,也很無知-請保持溫柔! :)

問題所在

struct stat *something;
stat("/etc/profile", something);

something是指向無處的未初始化指針,這會產生未定義的行為,因為stat會在無效地址上寫入某物。 使用malloc您可以為其分配內存,並將指向該已分配內存位置的指針傳遞給stat ,這就是它起作用的原因。

但你並不需要使用malloc為,只是不申報something作為指針:

struct stat something;
stat("/etc/profile", &something); // <-- look at the usage of &

stat您應使用&運算符,它返回指向something的指針。

在您的其他程序中

struct dirent *b; 
while (( b = readdir(a)) != NULL)

readdir返回指向有效位置的指針,該函數本身負責使用有效對象並返回指向該對象的指針。 但是,您不能執行free(b)

人readdir

返回值

成功后, readdir()返回一個指向dirent結構的指針。 (此結構可能是靜態分配的;請勿嘗試將其free(3) 。)

readdir返回一個指向struct dirent的指針。 這樣做: b = readdir(a)readdir返回的新值覆蓋值b

所以b先前已使用malloc調用中分配的內存進行了初始化,該值已被覆蓋,您現在可能會發生內存泄漏。

您可能想知道然后是否需要在readdir調用之后在b free調用。 要回答這個問題,您必須查閱文檔。 在這種情況下,答案是否定的

readdir的文檔中:

成功后,readdir()返回一個指向dirent結構的指針。 (此結構可能是靜態分配的;請勿嘗試將其釋放(3)。)

int main(){
        struct stat *something;
        stat("/etc/profile", something);
        printf("%d\n", something->st_gid);
        free(something);
        return 0;
}

上面的代碼有多個問題,

  1. 您正在使用something未指向有效的位置,並再次使用它作為一個緩沖區來存儲信息返回stat()

int stat(const char *路徑名,struct stat * statbuf);

stat()statbuf指向的緩沖區中返回有關文件的信息,因此您的statbuf (某物)應該是有效的緩沖區,其大小足以存儲文件信息,即struct stat大小。

  1. free(something);

來自free()手冊頁

如果傳遞給free()的參數與POSIX.1-2008中的函數返回的指針較早的指針不匹配,該函數像malloc()那樣分配內存,或者如果通過調用free()或realloc釋放了空間(),行為未定義。

現在來看其他代碼:

// - malloc question about this very next line
        struct dirent *b; 
        while (( b = readdir(a)) != NULL){
                printf("%s %lu\n", b->d_name, b->d_ino);
        }

讓我們來探討一下readdir()

struct dirent * readdir(DIR * dirp); readdir()函數返回一個指向dirent結構的指針,該結構表示dirp指向的目錄流中的下一個目錄條目。 在到達目錄流的末尾或發生錯誤時,它返回NULL。

你看readdir()返回一個指針struct dirent類型,這使得bstruct dirent *b的有效指針。 這就是為什么它起作用。

通常,任何指針,無論是int *ptr還是char *ptr還是struct student *ptr ,它都應具有valid address並且有效地址可以是動態分配的地址某些變量的地址

案例1struct stat *something; 這里有somethingstruct stat類型的指針,它是未初始化的。

當你做stat("/etc/profile", something); 您要存儲/etc/profile信息到something是未初始化。 代替此,您應該將/etc/profile的信息存儲到something地址或

struct stat info;
struct stat *something = &info;
stat("/etc/profile",something );

情況2struct dirent *b; bstruct dirent類型的指針,它也應具有有效地址。 b = readdir(a); readdir返回值已分配給b ,因此現在您可以執行b->d_name等。

readdir()的手冊頁

成功后,readdir()返回一個指向dirent結構的指針。 (此結構可能是靜態分配的;請勿嘗試將其釋放(3)。)

暫無
暫無

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

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