[英]c programming malloc question
刚刚得到有关c malloc()函数的查询。 我正在从文件中读取()x个字节以获取文件名的长度,例如'read(file,&namelen,sizeof(unsigned char)); '。
变量namelen是一个无符号字符类型,并以该类型(1字节)写入文件。 现在namelen具有文件名的长度,即namelen = 8(如果文件名是'data.txt'),加上末尾的/ 0,则可以正常工作。
现在,我有一个结构来记录文件信息,即文件名,文件长度,内容大小等。
struct fileinfo
{
char *name;
...... other variable like size etc
};
struct fileinfo *files;
问题:我想使files.name变量的大小为namelen的大小,即8,这样我就可以成功地将文件名写入其中,例如'files [i] .name = malloc(namelen)'
但是,我不希望它是malloc(sizeof(namelen)),因为那样会使它成为file.name [1],因为它的类型为unsigned char。 我希望它是存储在变量&namelen中的值,即8,所以file.name [8]以便data.txt可以从文件中作为8个字节读取()并直接写入file.name [8?
有没有办法做到这一点,我目前的代码是这样,并返回4而不是8
files[i].name = malloc(namelen);
//strlen(files[i].name) - returns 4
//perhaps something like
malloc(sizeof(&namelen)) but does not work
感谢您的任何建议
曾经尝试过建议的建议,但是我现在使用以下方法得到了分段错误错误:
printf("\nsizeofnamelen=%x\n",namelen); //gives 8 for data.txt
files[i].name = malloc(namelen + 1);
read(file, &files[i].name, namelen);
int len=strlen(files[i].name); printf("\nnamelen=%d",len);
printf("\nname=%s\n",files[i].name);
当我尝试使用该files [i] .name变量打开()文件时,它不会打开,因此似乎不会在read()&files [i] .name和strlen()内部写入数据,这也会导致隔离错误尝试打印文件名
strlen(name) + 1
个字节长(由于终止\\0
)。 namelen = strlen("data.txt")
(即8),则必须分配files[i].name = malloc(namelen + 1)
malloc()
分配的任何内存都是undefined 。 您不能在刚刚分配的内存上执行strlen()
-您必须先设置已分配的内存 strncpy( files[i].name, "data.txt", namelen + 1 )
, 然后才可以strlen( files[i].name )
您拥有的代码(几乎)是分配内存的正确方法,您需要为尾随的NULL字节包括空间:
files[i].name = malloc(namelen + 1);
请注意,此时字符串尚未初始化,因此strlen(files[i].name)
将返回随机的崩溃次数。 您可以使用memset()
将内存清零,然后strlen(files[i].name)
将返回0。如果从文件中读取数据, strlen(files[i].name)
将返回8。
malloc返回未初始化的内存,因此结果为
strlen(files[i].name)
之后
files[i].name = malloc(namelen);
未定义。
并且strlen
对字符进行计数,直到内存块中的第一个'\\ 0'字符为止-它不返回由以前的malloc
调用分配的内存块大小。
关于问题更新:
read
不会以'\\ 0'字符终止目标,这就是为什么会出现分段错误的原因。
插入一个
files[i].name[namelen] = '\0';
正确终止C字符串,应解决此问题。
另外,您可以使用calloc
代替malloc。
如果文件名不变,您可以提高效率,并在同一malloc()
分配文件名的结构和空间:
struct fileinfo *files = malloc(sizeof *files + namelen + 1);
files->name = (char *) (files + 1);
这将分配一个单独的内存块,该内存块足以容纳struct fileinfo
(即sizeof *files
字节)和以'\\ 0'结尾的文件名( namelen + 1
)。 第二行在结构本身之后的第一个字节处使结构点的name
成员。
然后,您可以继续进行操作,例如通过将另一个调用read()
加载来将文件名写入files->name
。
完成后,您可以通过一次调用free(files)
释放整个结构,包括文件名。
read(file, &files[i].name, namelen);
应该
read(file, files[i].name, namelen);
因为files [i] .name存储分配的缓冲区的地址。 由于读取的原型是无效的*,因此您的编译器可能会让您不通过传递char **而不是报告错误。
同样如maxschlepzig所说,不要忘记在缓冲区的末尾添加\\ 0。
您是否为文件分配了空间? 当前,它是struct fileinfo *文件;
假设您执行了以下操作:files = malloc(sizeof(struct fileinfo)* num_files);
printf("\nsizeofnamelen=%x\n",namelen); //gives 8 for data.txt
files[i].name = malloc(namelen + 1);
read(file, &files[i].name, namelen);
files[i].name[namelen] = '\0'; // NUL-terminate the string.
int len=strlen(files[i].name); printf("\nnamelen=%d",len);
printf("\nname=%s\n",files[i].name);
如果您不对字符串(file [i] .name)进行NUL终止,那么您将继续读取随机内容,并可能读取段错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.