繁体   English   中英

时间:2019-04-01标签:callocm编程

[英]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()内部写入数据,这也会导致隔离错误尝试打印文件名

  1. 字符串为strlen(name) + 1个字节长(由于终止\\0 )。
  2. 如果namelen = strlen("data.txt") (即8),则必须分配files[i].name = malloc(namelen + 1)
  3. 您使用malloc()分配的任何内存都是undefined 不能在刚刚分配的内存上执行strlen() -您必须先设置已分配的内存
  4. 只有分配了内存后,才能使用内存,即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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM