#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(){
struct stat *something;
stat("/etc/profile", something);
printf("%dn", something->st_gid);
free(something);
return 0;
}
$ ./a.out
Segmentation fault
我从这篇文章中了解到我需要使用 malloc 分配内存,所以我将其更改为如下所示,它有效:
- struct stat *something;
+ struct stat *something = malloc(sizeof(struct stat));
在之前但相关的练习中,我没有使用malloc,它已经奏效了。 我迷路了! 为什么我不需要malloc来表示下面的">*struct direntb;">行?
或者,换个说法,我们怎么知道有效载荷太多并使用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 %sn", argv[1]);
return 1;
}
// - malloc question about this very next line
struct dirent *b;
while (( b = readdir(a)) != NULL){
printf("%s %lun", b->d_name, b->d_ino);
}
int closing = closedir(a);
printf("in closing, status is %dn", 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()
返回指向 dirent 结构的指针。(此结构可能是静态分配的;不要尝试free(3)
它。
readdir
返回指向struct dirent
的指针。行为:b = readdir(a)
用readdir
返回的新值覆盖b
的值。
因此,b
之前使用malloc
调用中分配的内存初始化,该值已被覆盖,您现在可能有内存泄漏。
您可能想知道是否需要在readdir
呼叫后拨打free
b
。要回答这个问题,您必须查阅您的文档。在这种情况下,答案是否定的。
从readdir
文档中:
成功后,readdir() 返回一个指向 dirent 结构的指针。(这 结构可以静态分配;不要试图释放(3)它。
int main(){
struct stat *something;
stat("/etc/profile", something);
printf("%dn", something->st_gid);
free(something);
return 0;
}
上面的代码有多个问题,
- 您正在使用未指向有效位置的
something
,并且 再次使用它作为缓冲区来存储stat()
返回的信息。
int stat(const char *pathname, struct stat *statbuf);
stat()
返回有关文件的信息,在statbuf
指向的缓冲区中,因此您的statbuf
(某物)应该是一个有效的缓冲区,其大小足以存储文件的信息,即struct stat
的大小。
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 %lun", b->d_name, b->d_ino);
}
让我们readdir()
一下探索一下,
struct dirent *readdir(DIR *dirp);readdir() 函数返回一个 指向表示下一个目录条目的 dirent 结构的指针 DIRP 指向的目录流。 它在到达时返回 NULL。 目录流的结束或发生错误。
您会看到readdir()
返回一个struct dirent
类型的指针,该指针使b
struct dirent *b
有效的指针。这就是它奏效的原因。
通常任何指针无论是int *ptr
还是char *ptr
或struct student *ptr
,它都应该具有valid address
和有效的地址可以动态分配地址或某个变量的地址。
情况 1:struct stat *something;
这里something
是struct stat
类型的指针,并且未初始化。
当您执行stat("/etc/profile", something);
时,您正在尝试将/etc/profile
信息存储到未初始化的something
中。相反,您应该将/etc/profile
的信息存储到something
或
struct stat info;
struct stat *something = &info;
stat("/etc/profile",something );
情况2:struct dirent *b;
b
是struct dirent
类型的指针,它也应该有有效的地址。b = readdir(a);
readdir
返回值分配给b
,所以现在你可以执行b->d_name
等。
从readdir()
的手册页
成功后,readdir() 返回一个指向 dirent 结构的指针。 (这 结构可以静态分配;不要试图释放(3)它。