将字符*与另一个字符*长度相同的Mallocing字符*会导致它成为副本吗?
我目前正在尝试编写一个简单的C程序,该程序创建一个带有char*字段的结构,并将其赋值为与argv[1]相同的值。然后我想创建另一个与argv[1]长度相同的char*,但由于某些原因,其中的数据已经包含与argv[1]相同的值。以下是我目前的代码:将字符*与另一个字符*长度相同的Mallocing字符*会导致它成为副本吗?,c,gcc,C,Gcc,我目前正在尝试编写一个简单的C程序,该程序创建一个带有char*字段的结构,并将其赋值为与argv[1]相同的值。然后我想创建另一个与argv[1]长度相同的char*,但由于某些原因,其中的数据已经包含与argv[1]相同的值。以下是我目前的代码: #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> struct example{ c
#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;
}
这个代码是错误的
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
第二,你不能在这里释放“复制”,p->str指向它,你现在有一个悬空的指针。要复制和malloc,请使用strdup
获得相同字符串的原因是,您将字符串释放回堆,然后在调用malloc时再次获得字符串,这纯粹是运气,下次您可能会崩溃,得到垃圾,…请看以下几行:
char * copy = (char*)malloc(strlen(s));
...
p->str = copy;
free(copy);
return p;
您可以分配一块内存,初始化它,在结构中存储指向它的指针,然后释放它!从上的free()
开始,指针指向已释放的内存,即不能使用的内存
接下来会发生什么?你可以做另一件事:
char *w = (char *)malloc(strlen(t->str));
它碰巧从前面的代码中释放了get memory,而且由于malloc()
没有以任何方式初始化返回的内存,因此它恰好与您刚才使用的字符串相同
您看到的实际上是垃圾(未初始化的内存),它恰好是最近使用的文本的形状
总而言之,您的代码有三个问题:
create()中返回的字符串
clean()
中释放字符串malloc
不会初始化它分配的内存。对malloc
的第二次调用恰巧分配了第一次调用malloc
分配的相同内存块(正如调用free
时它已变得未分配一样)。你不能指望这一点
错误:
- 您还需要为NUL分配空间<代码>malloc(strlen)应该是
malloc(strlen)+1
- 当您打印
和试图查找其长度时,您可能无法访问未分配的内存。你可能不是有意要取消分配的<代码>免费(副本)代码>应移动到t->str
asclean
free(t->str)代码>
是strdup
+strlen
+malloc
的便捷快捷方式strcpy
- 如果你写信
而不是typedef struct { ... } example;
您可以使用struct example { ... };
而不是example
struct example
#包括
#包括
#包括
#包括
类型定义结构{
char*str;
}榜样;
示例*创建(字符*s){
示例*p=malloc(sizeof(示例));
p->str=strdup(s);
返回p;
}
作废新字符(示例*t){
printf(“原件:%s\n”,t->str);
char*w=strdup(t->str);
printf(“%s\n”,w);//打印未初始化的内存。
免费(w);
}
空洞清理(示例*t){
自由(t->str);
自由(t);
}
int main(int argc,字符**argv){
示例*p=create(argv[1]);
新(p),;
清洁(p);
返回0;
}
Hrre是问题所在:
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
您分配了原始字符串的副本并立即释放它
char *w = (char *)malloc(strlen(t->str));
这行代码重用以前释放的内存,这就是为什么您得到相同的内容-指针是相同的
注意,这种情况发生在非常简单的场景中,并且特定于您使用的c库。您的代码表现出未定义的行为。在调用
free
后,您不允许访问copy
,这就是您要做的。另外malloc
ingstrlen
字符不会为strcpy
malloc(strlen)添加的空终止符留下额外的字符代码>-->malloc(strlen+1)代码>不要认为malloc()
和free()
作用于指针变量——它们分配/释放与指针变量本身分离的内存块。。。指针变量只是用来保存地址,以便您知道在哪里可以找到它。在处理完放入malloc()
结果的指针变量后,不会释放该块——在处理完malloc()
ed的内存块后,会释放该块(尽管在此之前需要将其地址保留在某个位置)。如果不在create()函数中释放copy,将其释放为clean,是否也有效()像这样的方法:free(t->str);取决于你正在尝试做什么。当你不再需要字符串时,你需要释放它。如果你太早释放它,你会得到奇怪的行为,包括崩溃和损坏。如果你释放得太晚,你会有内存泄漏-欢迎来到CAh,好的,这是有意义的。同样对于p->str=strdup(s);在我的clean()中函数,我是否也需要释放(p->str);或者释放p,帮我解决这个问题吗?在c中,魔法不会发生任何事情,释放p不会释放p指向的任何东西,它不知道你没有另一个指针指向同一个字符串。但是在你的情况下,你应该释放(p->str);释放(p);因为我们知道p->str是一个“私有”副本
#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;
}
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
char *w = (char *)malloc(strlen(t->str));