我目前正在尝试编写一个简单的C程序,该程序使用char *字段创建一个struct,并将其赋值为与argv [1]相同的值。然后我想创建另一个与argv [1]长度相同的char *,但由于某种原因,里面的数据已经包含与argv [1]相同的值。到目前为止,这是我的代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
struct example{
char *str;
};
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
return p;
}
void new_char(struct example * t){
printf("original: %s\n", t->str);
char *w = (char *)malloc(strlen(t->str));
printf("why is this a copy? %s\n", w);
free(w);
}
void clean(struct example *t){
free(t);
}
int main(int argc, char **argv){
struct example * p = create(argv[1]);
new_char(p);
clean(p);
return 0;
}
然后当我使用GCC 6.1编译并运行该程序时,我得到了这个
> gcc -Wall -g -o test test.c
> ./test "test value here"
> original: test value here
> why is this a copy? test value here
答案 0 :(得分:7)
此代码错误
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
return p;
}
首先你需要分配strlen + 1
其次,你无法免费复制&#39;在这里,p-&gt; str指向它,你现在有一个悬空指针。复制和malloc使用strdup http://linux.die.net/man/3/strdup
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
p->str = strdup(s);
return p;
}
你获得相同字符串的原因是因为你把你的字符串释放回堆然后当你调用malloc时又把它取回来了,这纯粹是运气,另一次你可能崩溃,得到垃圾,...
答案 1 :(得分:2)
看看这一行:
char * copy = (char*)malloc(strlen(s));
...
p->str = copy;
free(copy);
return p;
你分配一块内存,初始化它,在你的结构中存储一个指针,然后释放它!从那个free()
开始,p->str
指针指向释放的内存,即不能使用的内存。
接下来会发生什么?你做了另一个:
char *w = (char *)malloc(strlen(t->str));
偶然地,从前面的代码中获取内存,并且由于malloc()
没有以任何方式初始化返回的内存,所以它恰好具有相同的字符串刚刚使用过。
你看到的实际上是垃圾(未初始化的内存)恰好采用了最近使用过的文本的形状。
总结一下,你的代码有三个问题:
create()
clean()
中释放字符串。答案 2 :(得分:2)
Hrre是问题所在:
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
您分配了原始字符串的副本并立即释放它。
char *w = (char *)malloc(strlen(t->str));
此行重用以前释放的内存,这就是为什么你得到相同的内容 - 指针是相同的。
请注意,这种情况非常简单,并且特定于您使用的c库。
答案 3 :(得分:1)
malloc
没有初始化它分配的内存。对malloc
的第二次调用碰巧分配了第一次调用malloc
已经分配的相同内存块(看到它在调用free
时已经未分配)。你不能指望这一点。
错误:
malloc(strlen(s))
应为malloc(strlen(s)+1)
。t->str
并尝试查找其长度时,您可能无法访问未分配的内存。你可能并不意味着解除分配它。 free(copy);
应移至clean
作为free(t->str);
。malloc
返回的值是必要的,但在C中是不必要的。提示:
strdup
是strlen
+ malloc
+ strcpy
的便捷快捷方式。如果你写
typedef struct { ... } example;
而不是
struct example { ... };
您可以使用example
代替struct example
。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
typedef struct {
char *str;
} example;
example* create(char *s){
example *p = malloc(sizeof(example));
p->str = strdup(s);
return p;
}
void new_char(example * t){
printf("original: %s\n", t->str);
char *w = strdup(t->str);
printf("%s\n", w); // Prints uninitialized memory.
free(w);
}
void clean(example *t){
free(t->str);
free(t);
}
int main(int argc, char **argv){
example * p = create(argv[1]);
new_char(p);
clean(p);
return 0;
}