简体   繁体   English

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

[英]c programming malloc question

Just got query regarding c malloc() function. 刚刚得到有关c malloc()函数的查询。 I am read()ing x number of bytes from a file to get lenght of filename, like ' read(file, &namelen, sizeof(unsigned char)); 我正在从文件中读取()x个字节以获取文件名的长度,例如'read(file,&namelen,sizeof(unsigned char)); ' . '。

The variable namelen is a type unsigned char and was written into file as that type (1 byte). 变量namelen是一个无符号字符类型,并以该类型(1字节)写入文件。 Now namelen has the lenght of filename ie namelen=8 if file name was 'data.txt', plus extra /0 at end, that working fine. 现在namelen具有文件名的长度,即namelen = 8(如果文件名是'data.txt'),加上末尾的/ 0,则可以正常工作。

Now I have a structure recording file info, ie filename, filelenght, content size etc. 现在,我有一个结构来记录文件信息,即文件名,文件长度,内容大小等。

   struct fileinfo
        {
              char *name;
              ...... other variable like size etc

        };
struct fileinfo *files;

Question: I want to make that files.name variable the size of namelen ie 8 so I can successfully write the filename into it, like ' files[i].name = malloc(namelen) ' 问题:我想使files.name变量的大小为namelen的大小,即8,这样我就可以成功地将文件名写入其中,例如'files [i] .name = malloc(namelen)'

However, I dont want it to be malloc(sizeof(namelen)) as that would make it file.name[1] as the size of its type unsigned char. 但是,我不希望它是malloc(sizeof(namelen)),因为那样会使它成为file.name [1],因为它的类型为unsigned char。 I want it to be the value thats stored inside variable &namelen ie 8 so file.name[8] so data.txt can be read() from file as 8 bytes and written straight into file.name[8? 我希望它是存储在变量&namelen中的值,即8,所以file.name [8]以便data.txt可以从文件中作为8个字节读取()并直接写入file.name [8?

Is there a way to do this my current code is this and returns 4 not 8 有没有办法做到这一点,我目前的代码是这样,并返回4而不是8

files[i].name = malloc(namelen);
//strlen(files[i].name) - returns 4

//perhaps something like
malloc(sizeof(&namelen)) but does not work

Thanks for any suggestions 感谢您的任何建议

Have tried suggested suggestions guys, but I now get a segmentation fault error using: 曾经尝试过建议的建议,但是我现在使用以下方法得到了分段错误错误:

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);  

When I try to open() file with that files[i].name variable it wont open so the data does not appear to be getting written inside the read() &files[i].name and strlen() causes segemntation error as well as trying to print the filename 当我尝试使用该files [i] .name变量打开()文件时,它不会打开,因此似乎不会在read()&files [i] .name和strlen()内部写入数据,这也会导致隔离错误尝试打印文件名

  1. a string is strlen(name) + 1 bytes long (because of the terminating \\0 ). 字符串为strlen(name) + 1个字节长(由于终止\\0 )。
  2. if namelen = strlen("data.txt") (ie 8) then you must allocate files[i].name = malloc(namelen + 1) 如果namelen = strlen("data.txt") (即8),则必须分配files[i].name = malloc(namelen + 1)
  3. any memory you allocate using malloc() is undefined . 您使用malloc()分配的任何内存都是undefined You cannot perform strlen() on memory you just allocated - you must set the memory you've allocated first 不能在刚刚分配的内存上执行strlen() -您必须先设置已分配的内存
  4. only after you allocate the memory can you use the memory, ie strncpy( files[i].name, "data.txt", namelen + 1 ) and only then can you strlen( files[i].name ) 只有分配了内存后,才能使用内存,即strncpy( files[i].name, "data.txt", namelen + 1 )然后才可以strlen( files[i].name )

The code you have is (almost) the correct way to allocate the memory, you need to include space for the trailing NULL byte: 您拥有的代码(几乎)是分配内存的正确方法,您需要为尾随的NULL字节包括空间:

files[i].name = malloc(namelen + 1);

Note that at this point the string is not initialized, so strlen(files[i].name) will either return a random number of crash. 请注意,此时字符串尚未初始化,因此strlen(files[i].name)将返回随机的崩溃次数。 You can use memset() to zero the memory and then strlen(files[i].name) will return 0. If you read the data from the file, strlen(files[i].name) will return 8. 您可以使用memset()将内存清零,然后strlen(files[i].name)将返回0。如果从文件中读取数据, strlen(files[i].name)将返回8。

malloc returns uninitialized memory, thus the result of malloc返回未初始化的内存,因此结果为

strlen(files[i].name)

directly after 之后

files[i].name = malloc(namelen);

is undefined. 未定义。

And strlen counts the characters until the first '\\0' character in a memory block - it does not return the memory block size allocated by a former malloc call. 并且strlen对字符进行计数,直到内存块中的第一个'\\ 0'字符为止-它不返回由以前的malloc调用分配的内存块大小。

Regarding question update: 关于问题更新:

A read does not terminate the destination with a '\\0' character, and this is why you get a segmentation fault. read不会以'\\ 0'字符终止目标,这就是为什么会出现分段错误的原因。

Inserting a 插入一个

files[i].name[namelen] = '\0';

properly terminates the C-string and should fix this issue. 正确终止C字符串,应解决此问题。

Alternatively you could use calloc instead of malloc. 另外,您可以使用calloc代替malloc。

If the filename won't change, you can be a bit efficient and allocate both the structure and the space for the filename in the same malloc() : 如果文件名不变,您可以提高效率,并在同一malloc()分配文件名的结构和空间:

struct fileinfo *files = malloc(sizeof *files + namelen + 1);
files->name = (char *) (files + 1);

This allocates a single block of memory which is large enough for the struct fileinfo (ie sizeof *files bytes) and the '\\0'-terminated filename ( namelen + 1 ). 这将分配一个单独的内存块,该内存块足以容纳struct fileinfo (即sizeof *files字节)和以'\\ 0'结尾的文件名( namelen + 1 )。 The second line make the name member of the struct point at the first byte after the struct itself. 第二行在结构本身之后的第一个字节处使结构点的name成员。

You can then go ahead and write the filename into files->name by eg loading it with another call to read() . 然后,您可以继续进行操作,例如通过将另一个调用read()加载来将文件名写入files->name

You can free the entire structure, including the filename, with a single call to free(files) when you're done with it. 完成后,您可以通过一次调用free(files)释放整个结构,包括文件名。

read(file, &files[i].name, namelen);

should be 应该

read(file, files[i].name, namelen);

Because files[i].name stores the address of the allocated buffer. 因为files [i] .name存储分配的缓冲区的地址。 Since the prototype for read is void* your compiler might be letting you get away with passing a char** rather than reporting an error. 由于读取的原型是无效的*,因此您的编译器可能会让您不通过传递char **而不是报告错误。

Also as maxschlepzig said, don't forget to add a \\0 to the end of the buffer. 同样如maxschlepzig所说,不要忘记在缓冲区的末尾添加\\ 0。

Did you allocate space for the files? 您是否为文件分配了空间? Currently, it is struct fileinfo * files; 当前,它是struct fileinfo *文件;

Assuming you did something like this: files = malloc(sizeof(struct fileinfo) * num_files); 假设您执行了以下操作: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);  

If you don't NUL-terminate the string (file[i].name) then you will keep reading random stuff and possibly segfault. 如果您不对字符串(file [i] .name)进行NUL终止,那么您将继续读取随机内容,并可能读取段错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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