繁体   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