2011-01-07 61 views
0

刚刚得到关于c malloc()函数的查询。我从文件中读取()x字节数来获得长度的文件名,如'read(文件,& name,sizeof(unsigned char)); '。c编程malloc问题

变量namelen是一个无符号字符类型,并作为该类型(1字节)写入文件。现在namelen的文件名长度如果namelen = 8,如果文件名是'data.txt',加上额外的/ 0结束,工作正常。

现在我有一个结构的录音文件信息,即文件名,filelenght,内容大小等

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]作为其类型的无符号字符的大小。我希望它是存储在变量& 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); 

当我尝试打开()与文件中的文件[I]。名称变量,它不会开这样的数据不会出现读取里面要获取写入()&个文件[I]。名称和strlen的()导致segemntation误差以及要打印的文件名

+0

更新了我有关您的分段故障的答案。 – maxschlepzig 2011-01-07 14:52:46

回答

3
  1. 字符串是strlen(name) + 1字节长(因为终止\0的)。
  2. 如果namelen = strlen("data.txt")(即,8),则必须分配files[i].name = malloc(namelen + 1)
  3. 你分配使用malloc()任何存储器是未定义。您无法在内存上执行strlen()你只是分配 - 你必须设置你只
  4. 分配首先在存储你分配后的内存可以你使用内存,即strncpy(files[i].name, "data.txt", namelen + 1)只有然后可以吗strlen(files[i].name)
+0

请仔细阅读以上关于分段错误错误编辑的问题 – daza166 2011-01-07 13:29:21

+0

`read()`后请加:`files [i] .name [namelen] ='\ 0';` - 发出`strlen )`在内存中没有'\ 0'(因为`strlen`只有在到达'\ 0`时才会停止计数)。 – 2011-01-07 14:13:22

+0

另外,改变`read(file,files [i] .name,namelen)` - 当你想写入指针指向的内存时,你试图写在指针的顶部(我认为你需要重写在指针和`&`操作符上读取K&R)。 – 2011-01-07 14:14:28

2

你的代码是(几乎)分配内存的正确途径,你需要包括结尾的空字节的空间:

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

请注意,此时字符串未初始化,因此strlen(files[i].name)将返回随机数的崩溃。您可以使用memset()来清零内存,然后strlen(files[i].name)将返回0.如果从文件读取数据,则strlen(files[i].name)将返回8。

1

malloc的返回未初始化的存储器,从而直接后

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

是未定义的的

strlen(files[i].name) 

结果。

strlen对字符进行计数直到内存块中的第一个'\ 0'字符为止 - 它不返回前malloc调用分配的内存块大小。

关于质询的更新:

一个read不终止与“\ 0”字符的目的,这就是为什么你会得到一个分段错误。

插入

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

正常终止C-字符串,应该可以解决这个问题。

或者,您可以使用calloc而不是malloc。

1

如果文件名也不会改变,可以是一个位有效和分配的结构和在同一malloc()的文件名的空间:

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

该分配的存储器中的单个块,其是对于struct fileinfo(即sizeof *files字节)和'\ 0'终止的文件名(namelen + 1)足够大。第二行使结构体的name成员位于结构本身之后的第一个字节处。

然后,您可以继续,通过例如将文件名写入files->name。用另一个电话read()加载它。

完成后,您可以通过一次性呼叫free(files)来释放整个结构,包括文件名。

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

如果你不NUL终止字符串(文件[i] .name),那么你会继续阅读随机的东西,可能seg段。

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

应该是

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

因为文件[I]。名称存储所分配的缓冲器的地址。由于用于读取的原型是无效的*您的编译器可能会让您通过char **而不是报告错误。

也如maxschlepzig所说,不要忘记在缓冲区的末尾添加\ 0。