使用包含多个元素的结构的 malloc
Use of malloc of a struct containing multiple elements
我在这里做错了什么?
我有一个 QueueElement 结构,其中包含一个 char* 文本和一个指向下一个元素的指针,因此显然是一个链表:
//QElement as in QueueElement
struct QElement {
char* text;
struct QElement* next;
};
typedef struct QElement QElement;
.....
void enqueue (char* string){
QElement *new = (QElement *)malloc(sizeof(QElement));
//QElement cast is probably redundant but it doesn't hurt anyone
strcpy (new->text, string);
//some other stuff happening here, linking to other element in linked list,
//but thats not of interest at the moment
}
.....
如果我尝试在 main 函数中加入一个词,我会不断收到分段错误,而 valgrind 告诉我,我在使用 strcpy 时做错了什么,所以我的 malloc 似乎不正确。我该怎么做?
在此代码中
strcpy (new->text, string);
new->text
没有分配内存。它可能包含一些垃圾值,或一些写保护内存地址甚至 NULL。将该指针传递给 strcpy()
会将您带到 Undefined behaviour,作为副作用,您可能会遇到分段错误。
您可以使用 strdup()
或在 strcpy()
指向该指针之前将内存分配给 new->text
。在这两种情况下,您之后都需要 free()
分配的内存。
此外,
- 请 do not cast
malloc()
的 return 值。
- 在使用指针之前检查动态内存分配是否成功[
malloc()
/calloc()
]。
因为你只为结构变量分配内存。您必须在结构成员中分配内存。
new->text=malloc(10);//for example
分配内存后就可以使用strcpy函数了
您已经为 new
分配了内存,但没有为 text
成员变量分配内存。
为text
分配内存并执行代码。
其他答案推荐的strdup(.)
不规范。如果您不在 Unix 平台上,它可能不可用。
不过这个观点是正确的。您需要分配内存来存储您的字符串。
尝试:
const size_t sz=(strlen(string)+1)*sizeof(*string);//Space required. Including '[=10=]' terminator.
new->text=malloc(sz);//space allocated.
if(new->text==NULL){//sz never 0 because +1.
exit(EXIT_FAILURE);//Allocation failed in non-error handled function.
}
memcpy(new->text,string,sz); //typically fastest way to copy!
而不是 strdup(.)
。
我对 sizeof(*string)
的使用实际上是不必要的(因为它始终为 1),但编译器会发现这一点,这只是一种很好的做法。
总有一天世界会更加统一地使用多字节字符,而这段代码已经为那个光荣的黎明做好了准备!
完成 'QElement' 后不要忘记 free(.)
。
你应该写一个像这样的函数:
void QElementDestroy(QElement*const element){
if(element==NULL){
return;//Nothing to do!
}
free(element->text);//Needs NULL protection.
free(element);//Does not need NULL protection. But we've done the test anyway!
//NB: Order matters here. A lot.
}
并在完成由 enqueue(.)
编辑的值 return 后调用它。
如果您希望字符串 'out live' 在调用 destroy 之前设置 element->text=NULL
元素。
free(NULL)
什么都不做,return 通常。
PS: 我认为 strdup(.)
有点像 n00b 陷阱。他们需要一段时间才能掌握匹配 malloc(.)
和 free(.)
的窍门,而 strdup(.)
有点叛逆,因为其他 str...
函数的 none 分配了 space 来电者预计 free(.)
。这也是非标准的。
我在这里做错了什么?
我有一个 QueueElement 结构,其中包含一个 char* 文本和一个指向下一个元素的指针,因此显然是一个链表:
//QElement as in QueueElement
struct QElement {
char* text;
struct QElement* next;
};
typedef struct QElement QElement;
.....
void enqueue (char* string){
QElement *new = (QElement *)malloc(sizeof(QElement));
//QElement cast is probably redundant but it doesn't hurt anyone
strcpy (new->text, string);
//some other stuff happening here, linking to other element in linked list,
//but thats not of interest at the moment
}
.....
如果我尝试在 main 函数中加入一个词,我会不断收到分段错误,而 valgrind 告诉我,我在使用 strcpy 时做错了什么,所以我的 malloc 似乎不正确。我该怎么做?
在此代码中
strcpy (new->text, string);
new->text
没有分配内存。它可能包含一些垃圾值,或一些写保护内存地址甚至 NULL。将该指针传递给 strcpy()
会将您带到 Undefined behaviour,作为副作用,您可能会遇到分段错误。
您可以使用 strdup()
或在 strcpy()
指向该指针之前将内存分配给 new->text
。在这两种情况下,您之后都需要 free()
分配的内存。
此外,
- 请 do not cast
malloc()
的 return 值。 - 在使用指针之前检查动态内存分配是否成功[
malloc()
/calloc()
]。
因为你只为结构变量分配内存。您必须在结构成员中分配内存。
new->text=malloc(10);//for example
分配内存后就可以使用strcpy函数了
您已经为 new
分配了内存,但没有为 text
成员变量分配内存。
为text
分配内存并执行代码。
strdup(.)
不规范。如果您不在 Unix 平台上,它可能不可用。
不过这个观点是正确的。您需要分配内存来存储您的字符串。
尝试:
const size_t sz=(strlen(string)+1)*sizeof(*string);//Space required. Including '[=10=]' terminator.
new->text=malloc(sz);//space allocated.
if(new->text==NULL){//sz never 0 because +1.
exit(EXIT_FAILURE);//Allocation failed in non-error handled function.
}
memcpy(new->text,string,sz); //typically fastest way to copy!
而不是 strdup(.)
。
我对 sizeof(*string)
的使用实际上是不必要的(因为它始终为 1),但编译器会发现这一点,这只是一种很好的做法。
总有一天世界会更加统一地使用多字节字符,而这段代码已经为那个光荣的黎明做好了准备!
完成 'QElement' 后不要忘记 free(.)
。
你应该写一个像这样的函数:
void QElementDestroy(QElement*const element){
if(element==NULL){
return;//Nothing to do!
}
free(element->text);//Needs NULL protection.
free(element);//Does not need NULL protection. But we've done the test anyway!
//NB: Order matters here. A lot.
}
并在完成由 enqueue(.)
编辑的值 return 后调用它。
如果您希望字符串 'out live' 在调用 destroy 之前设置 element->text=NULL
元素。
free(NULL)
什么都不做,return 通常。
PS: 我认为 strdup(.)
有点像 n00b 陷阱。他们需要一段时间才能掌握匹配 malloc(.)
和 free(.)
的窍门,而 strdup(.)
有点叛逆,因为其他 str...
函数的 none 分配了 space 来电者预计 free(.)
。这也是非标准的。