我是malloc的新手。所以我想测试这个小代码。 我收到"分段错误错误"。
**编辑:问题来自不分配char *名称(感谢@Zack) 您可以看到导致问题的原因:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct info { char *name; } fileinfo;
void mal (fileinfo **ptr)
{
if ((*ptr = (fileinfo*) malloc(3*sizeof(fileinfo))) == NULL) {
fprintf(stderr,"Memory allocating error #1\n");
exit(1);
}
//that what was causing the error - START
for (j = 0; j < 3; j += 1)
{
(*ptr)[j].name = (char*) malloc(10*sizeof(char*));
}
//that what was causing the error - END
strcpy(ptr[0]->name,"1. A\n"); //line 13
strcpy(ptr[1]->name,"2. B\n");
strcpy(ptr[2]->name,"3. C\n");
}
int main (int argc, char *argv[])
{
fileinfo *files;
int i;
mal(&files); //line 22
for (i = 0; i < 3; i += 1)
{
printf("name=%s\n",files[i].name);
}
free(files);
return 0;
}
使用valgrind:
==5751== Use of uninitialised value of size 8
==5751== at 0x4006EB: mal (mal1.c:13)
==5751== by 0x400747: main (mal1.c:22)
==5751==
==5751== Invalid write of size 4
==5751== at 0x4006EB: mal (mal1.c:13)
==5751== by 0x400747: main (mal1.c:22)
==5751== Address 0x0 is not stack'd, malloc'd or (recently) free'd
我做错了什么?! 提前谢谢。
答案 0 :(得分:1)
您的问题是您需要在复制之前分配ptr [i] - &gt;名称。指针本身指向一些随机的内存区域。要使用它,你必须获得安全的良好内存,这就是malloc和calloc以及(C ++中的新功能)所做的一切。你给出的例子仍然是一团糟,我的纠正并不是那么好,但你知道C和C ++中的每个指针都必须从某个地方分配。而且,另一方面,一旦你完成指针,你必须释放它们。
void mal (fileinfo **ptr, int count)
{
if ((*ptr = (fileinfo*) malloc(count*sizeof(fileinfo))) == NULL) {
fprintf(stderr,"Memory allocating error #1\n");
exit(1);
}
for (int i = 0; i < 3; i++) {
char buff[2];
buff[0] = 'A' + i;
buff[1] = 0;
ptr[i]->name = malloc( 10 );
strcpy(ptr[0]->name,"1. %s\n", buff);
}
}
答案 1 :(得分:0)
尝试
void mal (fileinfo **ptr) {
if ((*ptr = malloc(3*sizeof(fileinfo))) == NULL) {
perror("Memory allocating error #1\n");
exit(EXIT_FAILURE);
}
if (!(ptr[0]->name = strdup("1. A\n")))
{ perror("string 1"); exit(EXIT_FAILURE);};
if (!(ptr[1]->name = strdup("2. B\n")))
{ perror("string 2"); exit(EXIT_FAILURE);};
if (!(ptr[2]->name = strdup("3. C\n")))
{ perror("string 3"); exit(EXIT_FAILURE);} ;
}
顺便说一下,最好让它成为一个返回指针的函数,比如
fileinfo* make() {
fileinfo* ptr = malloc(3*sizeof(fileinfo)));
if (!ptr) { perror("make fileinfo"); exit(EXIT_FAILURE); };
if (!(ptr[0]->name = strdup("1. A\n")))
{ perror("string 1"); exit(EXIT_FAILURE);};
if (!(ptr[1]->name = strdup("2. B\n")))
{ perror("string 2"); exit(EXIT_FAILURE);};
if (!(ptr[2]->name = strdup("3. C\n")))
{ perror("string 3"); exit(EXIT_FAILURE);} ;
return ptr;
}
然后,你需要一个像
这样的析构函数void destroy(fileinfo*ptr) {
free (ptr[0]->name);
free (ptr[1]->name);
free (ptr[2]->name);
free (ptr);
}
在您free
的末尾调用而不是main
请注意,您的代码非常临时:名称的数量(即3)是完全内置的。这是错误的设计。至少应该将该常量命名为:
#define NB_FILES 3
实际上,更好的方法是使用灵活的数组成员声明您的结构:
typedef struct fileinfo_st {
unsigned nbfiles;
char* filenames[];
} Fileinfo;
有关详情,请参阅this。你甚至可以使用一个可变函数来制作这样的结构。
FIleinfo *make(int, ...);
您可以称之为
Fileinfo* ptr = make (3, "abc","def","ghijklmnop");
或者你可以决定最后一个可变参数是NULL
BTW,请阅读undefined behavior。你可能不幸的是你的程序没有崩溃但仍然是非常错误的。并使用gcc -Wall -g
进行编译,详细了解如何使用gdb
调试器和valgrind