返回信息流由于我定义了一个全局的结构变量,经常需要给该变量赋值,所以自己对malloc做了个测试。
测试代码如下:
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
main()
{
char* str=NULL;
str=(char *)malloc(sizeof(char)*5);
str="hope";
printf("str=%s\n",str);
printf("strlen(str)=%d\n",strlen(str));
str=(char *)malloc(sizeof(char)*3);
str="li";
printf("str=%s\n",str);
printf("strlen(str)=%d\n",strlen(str));
str=(char *)malloc(sizeof(char)*10);
str="If you try";
printf("str=%s\n",str);
printf("strlen(str)=%d\n",strlen(str));
getch();
}
测试结果如下:
str=hope
strlen(str)=4
str=li
strlen(str)=2
str=If you try
strlen(str)=10
问题如下:
如果为一个指针连续分配内存时,上一次分配的内存释放了吗?
上述代码的写法是否合理呢?
我这样做是否会造成内存泄露呢?
这是一条镜像帖。来源:北邮人论坛 / cpp / #74091同步于 2013/9/30
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
为一个指针用malloc分配两次内存会怎样???
xiu062458
2013/9/30镜像同步21 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
【 在 xiu062458 的大作中提到: 】
:
: 请问那怎么办呢?
1. C语言的话,只能自己记得free了。或者用别的内存分配方法,比如静态分配。或者自己写一个内存分配器,用malloc分配大块的内存,自己再细分。但总之自己必须知道什么时候分配什么时候回收。既然是C程序员,就有责任管理内存。
2. C++的话,RAII原则:每个资源(包括内存)有唯一的“主人”。一个对象创建的时候分配它拥有的资源,析构的时候释放资源。
3. 换用有垃圾回收的语言吧,比如LISP(这语言的历史比C还长,50年代就开始有垃圾回收了), ML, Haskell, Perl, Python, Java, Ruby, C#, Go ...
4. 用C和C++,同时使用BoehmGC垃圾回收器。这是个“保守”的垃圾回收器,即:因为C语言不知道一个对象的哪一部分是指针,所以BoehmGC必须假定对象的每个域都是指针。保守GC有可能不会及时回收一些垃圾,但保证不会出现无效的指针,而且如果对象内容被清0,它指向的对象是会回收的。最大的优势是用法很简单:把malloc全部换成GC_MALLOC,忘掉free,就行了。
5. 用C和C++,同时自己写垃圾回收算法。比如GTK+的GObject系统用引用计数。但是这是不完整的引用计数,因为无法回收循环垃圾。你可以实现Tracing,也可以实现“准确”(非保守)的GC。但可能用起来会很麻烦。
【 在 nuanyangyang 的大作中提到: 】
:
: 1. C语言的话,只能自己记得free了。或者用别的内存分配方法,比如静态分配。或者自己写一个内存分配器,用malloc分配大块的内存,自己再细分。但总之自己必须知道什么时候分配什么时候回收。既然是C程序员,就有责任管理内存。
: 2. C++的话,RAII原则:每个资源(包括内存)有唯一的“主人”。一个对象创建的时候分配它拥有的资源,析构的时候释放资源。
: ...................
果然是大神级别的回复,这么详细。
可是问题出现了:
暂且脱离开写的测试代码,我的主要目的是希望对一个全局的结构变量经常性的赋值。
我定义了一个全局的结构变量,形式如下:
typedef struct name{
char *first;
char *last;
}student;
本来,我是想用free来释放空间的,可是free后这个结构变量不就不存在了吗?
所以,每次对其赋值时,我进行深拷贝,以改变结构变量的值。可是结构里有指针,所以每次我都为这些指针分配了空间。
此问题怎么解呢?
这种一个对象引用另一个对象的情况是最麻烦的。这种情况建议还是换有垃圾回收的语言吧。
否则的话,你要想好first和last指向的对象的“主人”是谁。也就是想好:
1. 谁来分配first和last指向的字符串的内存。
2. 谁来回收这两个内存。
如果student本身不是主人,那就有别的部分负责这些内存的管理;
如果student是主人,还要分几种情况:
1. student要分配first和last的内存。也要回收它们
2. 内存会由别的地方创建,由student回收。这种情况要格外小心,不要让别的代码不小心把内存回收了,而student还留着悬垂引用。
方法一:变成连续空间
//
#define MAX_LENGTH 256
typedef struct name{
char first[MAX_LENGTH];
char last[MAX_LENGTH];
} student;
void func() {
student* p = (student*)malloc(sizeof(student));
free(p);
}
优点:一次malloc,一次free,代码简洁明了;缺点:成员长度固定,不能扩展,而且内存浪费很严重。
方法二:自己维护数据结构的alloc,free
//
typedef struct name{
char *first;
char *last;
} student, *student_pointer;
student_pointer create_student(char* f, int fc, char* l, int lc) {
int first_count = (fc > strlen(f))? fc : strlen(f);
int last_count = (lc > strlen(l))? lc : strlen(l);
student_pointer p = (student_pointer)malloc(sizeof(student) + first_count + last_count);
p->first = (char*)p + sizeof(student);
strcpy(p->first, f);
p->last = p->first + first_count;
strcpy(p->last, l);
}
void delete_student(student_pointer p) {
free(p);
}
void func() {
student_pointer p = create_student("Tony", 10, "Jansan", 10);
printf("First Name: %s\nLast Name: %s\n", p->first, p->last);
delete_student(p);
}
优点:一次malloc,一次free,内存长度可自行调节;缺点:需要自己维护内存结构。
【 在 xiu062458 的大作中提到: 】
:
: 果然是大神级别的回复,这么详细。
: 可是问题出现了:
: ...................
你一定要用C来写吗?不能用C++?(不能用string?)
如果以上问题回答都是是的话,用strdup,不然用C++
另外,即使是用C也有string库可用,人生苦短别不用轮子了
【 在 xiu062458 的大作中提到: 】
:
: 请问那怎么办呢?
最简单安全直接的做法就是不管--如果你的程序不是要运行20年的那种,也不是狂吃内存吃到操作系统穷的地步,那就不用管它,让你程序自动跑完后,操作系统自动回收所有内存就好了,这个不可能有泄漏。