计数指针 (Counter Pointer) 与 垃圾回收器 (Garbage Collection) 有何分别?
小弟一向都使用CounterPointer来处理调用new所产生的指针,一向都没有什麽问题,
所以不觉得须要有垃圾回收器的必要,我不知自己认知的是否正确,
牛哥们可以讨论一下 Counter Pointer 与 Garbage Collection 的分别在那里吗?
问题点数:100、回复次数:25Top
1 楼steedhorse(晨星)回复于 2006-11-21 09:43:02 得分 0
现在许多高效的GC都不采用CP机制了。Top
2 楼steedhorse(晨星)回复于 2006-11-21 09:45:48 得分 0
如果手工进行referrence counter,至少对程序员不透明,而GC对程序员完全是透明,程序员想用资源时尽管申请,别的啥也不用管。
当然,开发效率(甚至某种程度上的运行效率)的提高是以运行时空间占用为代价的。Top
3 楼Polarislee(北极星)(无房无车,飘在北京)回复于 2006-11-21 12:58:39 得分 0
Reference Counter有几个最致命的缺陷
1. 无法释放有循环引用对象。
2. 在进行对象遍历的时候十分影响效率
3. 在多线程共享对象时,需要十分注意处理竞争条件Top
4 楼OnlyHappy(说好不打脸)回复于 2006-11-21 13:02:16 得分 0
还是C爽。。Mark 一把Top
5 楼Polarislee(北极星)(无房无车,飘在北京)回复于 2006-11-21 13:03:36 得分 0
至于GC的实现方式有很多,细节可以写一本书(的确有这样一本书可以买到)
常用的GC算法可以释放循环引用,不会影响对象操作的效率,而且实现线程安全的(实际上GC的时候会暂停正在处理的线程)。
但是通常GC会导致程序的相应性能下降,而且GC的很多行为是不能预测的,不利于在实时系统中的应用。Top
6 楼Polarislee(北极星)(无房无车,飘在北京)回复于 2006-11-21 13:07:24 得分 0
从OnlyHappy的话来看,总感觉C/C++的程序员对GC有一种天然的抗拒心理,其实大可不必。无论是手动管理,智能指针还是GC不过都是内存管理的方式而已。各有各的优缺点和适应性。
不可否认,在绝大多数情况下,GC可以极大地减轻developer的负担,提高开发效率并减少错误。Top
7 楼OnlyHappy(说好不打脸)回复于 2006-11-21 13:14:47 得分 0
>>不可否认,在绝大多数情况下,GC可以极大地减轻developer的负担,提高开发效率并减少错?>>误。
是的。能提高开发效率,但是作了包装后,总觉得不透明,别人做GC功能肯定要考虑到很多方面的东西。其实有很多情况下并不要多线程什么的。这个就有点浪费了。。。。Top
8 楼steedhorse(晨星)回复于 2006-11-21 13:27:01 得分 0
//其实有很多情况下并不要多线程什么的。这个就有点浪费了。。。。
——“不要多线程”跟“不要GC”并没有什么直接联系或因果关系啊。Top
9 楼owlling(owlman)回复于 2006-11-21 13:33:39 得分 0
只能说指针计数可能是GC的一种手段而已,而且现在来看这种手段并不怎么有效、
另外,多线程和gc更不说不到一起去。他们各自属于的内存管理层次都是不同的。。Top
10 楼gameboy007(WoHaHa-WaHaHaHaHa)回复于 2006-11-21 16:20:37 得分 0
>> steedhorse(晨星) :
>> 现在许多高效的GC都不采用CP机制了。
如果GC不用Counter来记下有多少个地方使用这个指针,
那麽又可以用什麽方法?我想GC总得也要释放没有使用
的指针吧,当中不用counter机制还可以用什麽呢?
>> 如果手工进行reference counter,至少对程序员不透明,而GC对程序员完全是透明...
不明白"手工进行reference counter"的意思,但我也有一个感觉,就是当一个CounterPointer
被多个地方同时使用时,的确有那种不透明的感觉。
那麽可否描述一下GC是如何提供透明度?
>> Polarislee(北极星):
>> 1. 无法释放有循环引用对象
我想这真是致命的缺陷,虽然循环引用的机会非常少见,当这种事情发生
也是代表了程式设计出问题。
>> 2. 在进行对象遍历的时候十分影响效率
这点我听不懂,可以说多点吗?
>> OnlyHappy(说好不打脸) :
>> 还是C爽
我不太认同这种说法,我开发C程序多年,如果是写一个小程式,C真的很爽,但开发大型程式
时我没有见过C程序员是爽的,这也是我们公司在4年前全面转用C++的原因,我的经验是在小型
程式中C是C++代码的70%,一但开发大型程式,C代码多出C++代码2至3倍!还爽吗?
当然这只是小弟个人的经验,或者我的C程序写得差吧。: )
Top
11 楼steedhorse(晨星)回复于 2006-11-22 13:01:23 得分 0
To:gameboy007(WoHaHa-WaHaHaHaHa)
我不知道北极星说的那本专讲GC实现的书是哪本。你可以问问他,买来看看。
但我知道《Programming Microsoft .net Framework Applications》(好像是这个名字),讲到了.net平台上GC的实现,虽然不算特别详尽,但至少可以让人明白个大概。你可以买来看看。:)
另外,《Inside Java Virtual Machine》一书应该也可以买来看看。Top
12 楼mLee79()回复于 2006-11-22 15:14:57 得分 0
GC 通常可以这样实现 ...
* 标记-清除, 让所有的活动的对象自己做一个标记, 最后没有做标记的对象被清除 ...
* 想想自己在整理物品的时候怎么做的就知道了, 把有用的东西放在个新的地方, 剩下的就被回收 ....
基于 cp 的很难有一个通用的高效的机制实现, 貌似历史上就基本上没被使用过, 不过对些特定的数据类型是最高效的, 不过感觉上不算是 gc ...
实际上, c 里用 gc 方便多了, 一般人我还不告诉他 ...
Top
13 楼chengyimin()回复于 2006-11-23 21:26:18 得分 0
请问楼上的,标记-清除怎么环形应用的?
一直想不通...Top
14 楼steedhorse(晨星)回复于 2006-11-23 21:36:34 得分 0
标记-清除法,对于没有用了的对象,既使它里边有环,也根本标记不到了,所以干粹就统统扔了。Top
15 楼FantasyNES()回复于 2006-11-24 17:11:59 得分 0
http://www.china-pub.com/computers/common/info.asp?id=18468
这本专门讲gc的,说的不错Top
16 楼gameboy007(WoHaHa-WaHaHaHaHa)回复于 2006-11-24 19:49:17 得分 0
谢谢! steedhorse(晨星) , FantasyNES() 提供的
Programming Microsoft .net Framework Applications
Inside Java Virtual Machine
http://www.china-pub.com/computers/common/info.asp?id=18468 (垃圾回收)
我去书店一定会留意这三本书!
>> mLee79()
>> 实际上, c 里用 gc 方便多了, 一般人我还不告诉他 ...
C如可实现垃圾回收?垃圾回收代表了一种自动化,但C是必须要调用函数才能
工作的,那麽如何在离开scope时自动回收垃圾呢,C是没有destructor这东西的,
是否须要多线程才能做到?有没有一些例子?Top
17 楼owlling(owlman)回复于 2006-11-24 19:52:19 得分 0
随便提下。现在的gc和图论倒是有很多联系的,呵呵,,,Top
18 楼mLee79()回复于 2006-11-24 21:35:50 得分 0
我通常的认为 gc 是一种资源管理的思想, 而不仅仅是程序员偷懒的手段, 在 C 中使用 gc 基本上可以做到除了在内存不足的时候所发生的gc之外对程序员将是透明的, 对性能的影响也将相当的小 , C 是用于系统编程的, 显然不可能假定运行于多任务多线程的环境, 当然在多线程环境下也可以起一个 idle 线程专门做 gc 工作, 不过感觉上没啥必要 ...
大概就做成这个样子 :
foobar()
{
int *buff1 , *buff2;
__GC_CTX_push();
buff1 = __GC_malloc( 100 , __GC_TEMP_BUFF | __GC_POD );
buff2 = __GC_malloc( 100 , __GC_PREV_CTX | __GC_POD );
$use( buff1 , buff2 , pInt , pStrArr , pObj , pObj2 );
__GC_CTX_pop(); // buff1 被 gc 回收 , buff2 要直到下一次 __GC_RETURN , __GC_CTX_pop 才参加 gc ..
}
foo1()
{
int * pInt;
__X_string * pStrArr;
__X_Object * pObj , * pObj2;
__GC_ENV_INIT;
pInt = __GC_malloc( 1024 * sizeof( int ) , __GC_TEMP_BUFF | __GC_POD );
pStrArr = __GC_malloc( 100 * sizeof( __X_string ) , __GC_CURR_CTX | __GC_BY_REF_COUNT , __X_string_destroy );
pObj = __GC_malloc( sizeof( __X_Object ) , __GC_CURR_CTX | __GC_OBJECT , __X_Object_destroy , __X_Object_mark );
pObj2 = __GC_malloc( sizeof( __YY_Object ) , __GC_CURR_CTX | __GC_OBJECT_VTBL , __YY_Object_vtbl );
foobar( pInt , pStrArr , pObj , pObj2 );
if( xxx )
__GC_RETURN( FAILED );
__GC_RETURN( SUCCESS ); // pInt, foobar.buff2 被 gc 回收 .....
}
runFunc1()
{
__GC_CTX_push();
foo1();
__GC_CTX_pop(); // pStrArr , pObj , pObj2 参加 gc ....
}
appEntry ()
{
__GC_CTX_new();
runFunc1();
__GC_CTX_destroy();
}
Top
19 楼gameboy007(WoHaHa-WaHaHaHaHa)回复于 2006-11-25 20:12:01 得分 0
谢谢 mLee79() 的 C 的 GC 程式段落,虽然看了C的GC实验,但个人觉得
C要废这麽大段程式码才做了这麽少。这也是C得短点,在每离开scope
时都要调用 __GC_CTX_pop() 这点上就不显得自动化和优雅了,但这也是没
办法,用C就是要有这种不怕苦的性格。
我看出虽然C实现GC需要的程式码比C++多得多,但在背後也显出C程式码
一板一眼,比C++少了好多看不出的缺陷。
>> 我通常的认为 gc 是一种资源管理的思想, 而不仅仅是程序员偷懒的手段, .....
另外非常同意 mLee79() 说的以上那段话!
我觉得每个C/C++程序员都需要有实现资源管理这种能力,因为在整个
程序中只有不多过10%的程式码是要最优化的,还有C/C++本身的速度就很快,
没有必要在所有的程式段中都需要原始指针,所以我觉得C/C++程序应该大量
使用Counter Pointer、Smart Pointer或者Garbage Collection来减少程序负担。Top
20 楼FantasyNES()回复于 2006-11-26 09:15:42 得分 0
mame里面也实现了一个类似gc的东西,不过简单多了
/***************************************************************************
Resource tracking code
***************************************************************************/
/*-------------------------------------------------
auto_malloc_add - add pointer to malloc list
-------------------------------------------------*/
INLINE void auto_malloc_add(void *result)
{
/* make sure we have tracking space */
if (malloc_list_index == malloc_list_size)
{
void **list;
/* if this is the first time, allocate 256 entries, otherwise double the slots */
if (malloc_list_size == 0)
malloc_list_size = 256;
else
malloc_list_size *= 2;
/* realloc the list */
list = realloc(malloc_list, malloc_list_size * sizeof(list[0]));
if (list == NULL)
fatalerror("Unable to extend malloc tracking array to %d slots", malloc_list_size);
malloc_list = list;
}
malloc_list[malloc_list_index++] = result;
}
/*-------------------------------------------------
auto_malloc_free - release auto_malloc'd memory
-------------------------------------------------*/
static void auto_malloc_free(void)
{
/* start at the end and free everything till you reach the sentinel */
while (malloc_list_index > 0 && malloc_list[--malloc_list_index] != NULL)
free(malloc_list[malloc_list_index]);
/* if we free everything, free the list */
if (malloc_list_index == 0)
{
free(malloc_list);
malloc_list = NULL;
malloc_list_size = 0;
}
}
/*-------------------------------------------------
begin_resource_tracking - start tracking
resources
-------------------------------------------------*/
void begin_resource_tracking(void)
{
/* add a NULL as a sentinel */
auto_malloc_add(NULL);
/* increment the tag counter */
resource_tracking_tag++;
}
/*-------------------------------------------------
end_resource_tracking - stop tracking
resources
-------------------------------------------------*/
void end_resource_tracking(void)
{
/* call everyone who tracks resources to let them know */
auto_malloc_free();
timer_free();
state_save_free();
/* decrement the tag counter */
resource_tracking_tag--;
}
/*-------------------------------------------------
auto_malloc - allocate auto-freeing memory
-------------------------------------------------*/
void *_auto_malloc(size_t size, const char *file, int line)
{
void *result;
/* fail horribly if it doesn't work */
result = _malloc_or_die(size, file, line);
/* track this item in our list */
auto_malloc_add(result);
return result;
}
/*-------------------------------------------------
auto_strdup - allocate auto-freeing string
-------------------------------------------------*/
char *auto_strdup(const char *str)
{
return strcpy(auto_malloc(strlen(str) + 1), str);
}Top
21 楼gameboy007(WoHaHa-WaHaHaHaHa)回复于 2006-11-27 13:02:12 得分 0
谢谢FantasyNES() 提供MAME的GC
由MAME这段GC程式码可以看出C与C++的根本不同,经由_auto_malloc 的调用提
取指针,而在_auto_malloc背後调用auto_malloc_free登记这个指针,当程序员认为
不再需要时调用auto_malloc_free把整个malloc_list free了。
但这存在一个问题,就是在begin_resource_tracking与end_resource_tracking之间
的程序中指针复制问题,就是说在某个或多个地方也正在使用这个指针时,
如果调用end_resource_tracking就会杀了这些正在某处使用的指针,即是说我们要在
任何时间都要记住有没有其他指针同时使用这个所为的 resource pointer才可调用
end_resource_tracking。
当然我觉得这是可以改善的,就是每当复制一个resource pointer时都调用一个好像
这样的一个函数:
int* b = copy_resource_pointer( a ); <-- 函数背後进行一些计数工作
当不要这个指针时就须要一个像这样的函数
despose_pointer( b ); <-- 函数背後把这个已登记的指针counter减一
在GC这点上C++与C存有明显分别,C++有Constructor、Destructor和Copy Constructor,
当我们产生一个Object复制Object或当Object离开scope时,constructor、copy constructor
和Destructor会在我们背後自动完成它们应该的任务,这就型成一种自动化,在GC上更能
打做出优雅的程式码与行为,所以小弟觉得C++实现GC比C好一点。
不知小弟看法有否错误,大家有何意见?Top
22 楼DrawText(hDC,"阅尽A片,心中无码,戒手淫!",14,lpRect,DT_TOP)回复于 2006-12-22 22:52:32 得分 0
学到不少!Top
23 楼ReverseEngineering(★给我一杯壮阳水☆换我一夜不下垂★男人阳萎不是罪☆)回复于 2006-12-23 20:01:00 得分 0
学习!Top
24 楼rulary(秦枫)回复于 2007-01-18 11:25:06 得分 0
收藏Top
25 楼classpatterns(一个2007毕业的小菜菜<闭关修炼ing>)回复于 2007-01-30 15:51:12 得分 0
xuexi...Top




