有谁用过Cacheman?(一个内存工具,可以定时整理内存碎片)我想知道其实现原理。

111222 2002-03-15 02:22:50
有代码最好!
肯定是有什么API的。
...全文
263 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
Hover 2002-05-29
  • 打赏
  • 举报
回复
给你贴篇文章

条款7:预先准备好内存不够的情况

operator new在无法完成内存分配请求时会抛出异常(以前的做法一般是返回0,一些旧一点的编译器还这么做。你愿意的话也可以把你的编译器设置成这样。关于这个话题我将推迟到本条款的结尾处讨论)。大家都知道,处理内存不够所产生的异常真可以算得上是个道德上的行为,但实际做起来又会象刀架在脖子上那样痛苦。所以,你有时会不去管它,也许一直没去管它。但你心里一定还是深深地隐藏着一种罪恶感:万一new真的产生了异常怎么办?

你会很自然地想到处理这种情况的一种方法,即回到以前的老路上去,使用预处理。例如,c的一种常用的做法是,定义一个类型无关的宏来分配内存并检查分配是否成功。对于c++来说,这个宏看起来可能象这样:


#define new(ptr, type) \
try { (ptr) = new type; } \
catch (std::bad_alloc&) { assert(0); }

(“慢!std::bad_alloc是做什么的?”你会问。bad_alloc是operator new不能满足内存分配请求时抛出的异常类型,std是bad_alloc所在的名字空间(见条款28)的名称。“好!”你会继续问,“assert又有什么用?”如果你看看标准c头文件<assert.h>(或与它相等价的用到了名字空间的版本<cassert>,见条款49),就会发现assert是个宏。这个宏检查传给它的表达式是否非零,如果不是非零值,就会发出一条出错信息并调用abort。assert只是在没定义标准宏ndebug的时候,即在调试状态下才这么做。在产品发布状态下,即定义了ndebug的时候,assert什么也不做,相当于一条空语句。所以你只能在调试时才能检查断言(assertion))。

new宏不但有着上面所说的通病,即用assert去检查可能发生在已发布程序里的状态(然而任何时候都可能发生内存不够的情况),同时,它还在c++里有另外一个缺陷:它没有考虑到new有各种各样的使用方式。例如,想创建类型t对象,一般有三种常见的语法形式,你必须对每种形式可能产生的异常都要进行处理:


new t;
new t(constructor arguments);
new t[size];

这里对问题大大进行了简化,因为有人还会自定义(重载)operator new,所以程序里会包含任意个使用new的语法形式。

那么,怎么办?如果想用一个很简单的出错处理方法,可以这么做:当内存分配请求不能满足时,调用你预先指定的一个出错处理函数。这个方法基于一个常规,即当operator new不能满足请求时,会在抛出异常之前调用客户指定的一个出错处理函数——一般称为new-handler函数。(operator new实际工作起来要复杂一些,详见条款8)

指定出错处理函数时要用到set_new_handler函数,它在头文件<new>里大致是象下面这样定义的:


typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();

可以看到,new_handler是一个自定义的函数指针类型,它指向一个没有输入参数也没有返回值的函数。set_new_handler则是一个输入并返回new_handler类型的函数。

set_new_handler的输入参数是operator new分配内存失败时要调用的出错处理函数的指针,返回值是set_new_handler没调用之前就已经在起作用的旧的出错处理函数的指针。

可以象下面这样使用set_new_handler:


// function to call if operator new can't allocate enough memory
void nomorememory()
{
cerr << "unable to satisfy request for memory\n";
abort();
}

int main()
{
set_new_handler(nomorememory);
int *pbigdataarray = new int[100000000];

...

}

假如operator new不能为100,000,000个整数分配空间,nomorememory将会被调用,程序发出一条出错信息后终止。这就比简单地让系统内核产生错误信息来结束程序要好。(顺便考虑一下,假如cerr在写错误信息的过程中要动态分配内存,那将会发生什么...)

operator new不能满足内存分配请求时,new-handler函数不只调用一次,而是不断重复,直至找到足够的内存。实现重复调用的代码在条款8里可以看到,这里我用描述性的的语言来说明:一个设计得好的new-handler函数必须实现下面功能中的一种。
·产生更多的可用内存。这将使operator new下一次分配内存的尝试有可能获得成功。实施这一策略的一个方法是:在程序启动时分配一个大的内存块,然后在第一次调用new-handler时释放。释放时伴随着一些对用户的警告信息,如内存数量太少,下次请求可能会失败,除非又有更多的可用空间。
·安装另一个不同的new-handler函数。如果当前的new-handler函数不能产生更多的可用内存,可能它会知道另一个new-handler函数可以提供更多的资源。这样的话,当前的new-handler可以安装另一个new-handler来取代它(通过调用set_new_handler)。下一次operator new调用new-handler时,会使用最近安装的那个。(这一策略的另一个变通办法是让new-handler可以改变它自己的运行行为,那么下次调用时,它将做不同的事。方法是使new-handler可以修改那些影响它自身行为的静态或全局数据。)
·卸除new-handler。也就是传递空指针给set_new_handler。没有安装new-handler,operator new分配内存不成功时就会抛出一个标准的std::bad_alloc类型的异常。
·抛出std::bad_alloc或从std::bad_alloc继承的其他类型的异常。这样的异常不会被operator new捕捉,所以它们会被送到最初进行内存请求的地方。(抛出别的不同类型的异常会违反operator new异常规范。规范中的缺省行为是调用abort,所以new-handler要抛出一个异常时,一定要确信它是从std::bad_alloc继承来的。想更多地了解异常规范,参见条款m14。)
·没有返回。典型做法是调用abort或exit。abort/exit可以在标准c库中找到(还有标准c++库,参见条款49)。

上面的选择给了你实现new-handler函数极大的灵活性。

处理内存分配失败的情况时采取什么方法,取决于要分配的对象的类:


class x {
public:
static void
outofmemory();

...

};

class y {
public:
static void outofmemory();

...

};

x* p1 = new x; // 若分配成功,调用x::outofmemory
y* p2 = new y; // 若分配不成功,调用y::outofmemory

c++不支持专门针对于类的new-handler函数,而且也不需要。你可以自己来实现它,只要在每个类中提供自己版本的set_new_handler和operator new。类的set_new_handler可以为类指定new-handler(就象标准的set_new_handler指定全局new-handler一样)。类的operator new则保证为类的对象分配内存时用类的new-handler取代全局new-handler。

假设处理类x内存分配失败的情况。因为operator new对类型x的对象分配内存失败时,每次都必须调用出错处理函数,所以要在类里声明一个new_handler类型的静态成员。那么类x看起来会象这样:


class x {
public:
static new_handler set_new_handler(new_handler p);
static void * operator new(size_t size);

private:
static new_handler currenthandler;
};

类的静态成员必须在类外定义。因为想借用静态对象的缺省初始化值0,所以定义x::currenthandler时没有去初始化。


new_handler x::currenthandler; //缺省设置currenthandler为0(即null)
类x中的set_new_handler函数会保存传给它的任何指针,并返回在调用它之前所保存的任何指针。这正是标准版本的set_new_handler所做的:


new_handler x::set_new_handler(new_handler p)
{
new_handler oldhandler = currenthandler;
currenthandler = p;
return oldhandler;
}

最后看看x的operator new所做的:
1. 调用标准set_new_handler函数,输入参数为x的出错处理函数。这使得x的new-handler函数成为全局new-handler函数。注意下面的代码中,用了"::"符号显式地引用std空间(标准set_new_handler函数就存在于std空间)。

2. 调用全局operator new分配内存。如果第一次分配失败,全局operator new会调用x的new-handler,因为它刚刚(见1.)被安装成为全局new-handler。如果全局operator new最终未能分配到内存,它抛出std::bad_alloc异常,x的operator new会捕捉到它。x的operator new然后恢复最初被取代的全局new-handler函数,最后以抛出异常返回。

3. 假设全局operator new为类型x的对象分配内存成功,, x的operator new会再次调用标准set_new_handler来恢复最初的全局出错处理函数。最后返回分配成功的内存的指针。
c++是这么做的:


void * x::operator new(size_t size)
{
new_handler globalhandler = // 安装x的new_handler
std::set_new_handler(currenthandler);

void *memory;

try { // 尝试分配内存
memory = ::operator new(size);
}

catch (std::bad_alloc&) { // 恢复旧的new_handler
std::set_new_handler(globalhandler);
throw; // 抛出异常
}
std::set_new_handler(globalhandler); // 恢复旧的new_handler
return memory;
}

如果你对上面重复调用std::set_new_handler看不顺眼,可以参见条款m9来除去它们。

使用类x的内存分配处理功能时大致如下:


void nomorememory();// x的对象分配内存失败时调用的new_handler函数的声明

x::set_new_handler(nomorememory);
// 把nomorememory设置为x的
// new-handling函数
x *px1 = new x;
// 如内存分配失败,
// 调用nomorememory
string *ps = new string;
// 如内存分配失败,调用全局new-handling函数

x::set_new_handler(0);
// 设x的new-handling函数为空

x *px2 = new x;
// 如内存分配失败,立即抛出异常
// (类x没有new-handling函数)

你会注意到,处理以上类似情况,如果不考虑类的话,实现代码是一样的,这就很自然地想到在别的地方也能重用它们。正如条款41所说明的,继承和模板可以用来设计可重用代码。在这里,我们把两种方法结合
neccui 2002-04-13
  • 打赏
  • 举报
回复
怎么问题成了_set_new_handler的问题了。

这个内存不足是C++库报的还是windows系统报的?
_liang_ 2002-04-13
  • 打赏
  • 举报
回复
蛮有意思,有一点不理解:
既然NEW很大的内存就能将内存"碎片"整理,那任何程序运行时,碰到NEW,系统自然
会将内存碎片收集,整理,何需另外费周折
neccui 2002-04-13
  • 打赏
  • 举报
回复
那_set_new_handler当然截不到系统的报错了。
111222 2002-04-13
  • 打赏
  • 举报
回复
neccui(PPC) :

系统报的吧……

“内存不足”

111222 2002-04-12
  • 打赏
  • 举报
回复
up
111222 2002-04-12
  • 打赏
  • 举报
回复
我的代码是这样写的:


#include <new.h>

int handle_program_memory_depletion( size_t );

void main( void )
{
// Register existence of a new memory handler.
_set_new_handler( handle_program_memory_depletion );
size_t *pmemdump = new size_t[111222222];
}

int handle_program_memory_depletion( size_t size )
{
return 1;
}



结果照样蹦出“内存不足”对话框
wangsitao 2002-04-12
  • 打赏
  • 举报
回复
听课
wenzuodan 2002-04-12
  • 打赏
  • 举报
回复
直接去申请用户想要释放的容量的内存
neccui 2002-04-12
  • 打赏
  • 举报
回复
cache man的作用究竟是什么?
内存碎片?内存里哪里有什么碎片,即使有,又何须整理。

如果是强制释放磁盘的缓存倒有可能。
fhbkyo 2002-04-12
  • 打赏
  • 举报
回复
UP
111222 2002-04-12
  • 打赏
  • 举报
回复
曾经有一个很ft地帖子摆在我面前
我没有跟
等到结帖地时候我才追悔莫及
人世间最痛苦地事莫过与此了
如果上天能够给我一个再来一次的机会
我会跟:“UP”
如果一定要加上一个长度,我希望是一万个字节(=5000个UP)
111222 2002-04-12
  • 打赏
  • 举报
回复
_set_new_handler不好使啊
neccui 2002-04-12
  • 打赏
  • 举报
回复
不要试图new很大的内存。
如果失败了还好,恐怖的是成功了。
windows 系统会动用虚拟内存,拼命的写盘。磁盘写满了才失败。


要这样干也要用 API,强制在物理内存中分配,不过这样也很恐怖,别的程序估计都可能会垮掉。所以还是不要这样干了,呵呵。
111222 2002-04-12
  • 打赏
  • 举报
回复
DavidHowe:
你有演示代码么?为什么我new很大的内存会直接导致失败而系统不整理内存
111222 2002-03-16
  • 打赏
  • 举报
回复
DavidHowe:

那么,你想没想过,Windows的内存整理又是如何实现的呢?Windows自己肯定也是用API的吧
DavidHowe 2002-03-15
  • 打赏
  • 举报
回复
sorry,前面说错了一点,我忘了后来我不是那样做的。不是逐渐申请
越来越多的内存,而是直接去申请用户想要释放的容量的内存,一次就
搞定了。
我是和Rambooster.exe(也是一个类似的工具)进行比较,发现释放的
速度差不多,CPU的利用率也差不多,都挺高的。只是释放的容量不够
准确,和用户的意愿有些差距。
pigczc 2002-03-15
  • 打赏
  • 举报
回复
本来系统自动释放 各个已结束进程的占用内存, 但是 该 动作的优先级很低
, 而 类似此类程序只是提高了该动作的优先级, 让系统赶紧释放!
哈哈, 这是我的理解, 具体如何实现, goto Wondows programming, or sth else!
111222 2002-03-15
  • 打赏
  • 举报
回复
DavidHowe() :

你的这个方法太恐怖了一点吧……

UP
DavidHowe 2002-03-15
  • 打赏
  • 举报
回复
补充:为了避免系统为你弹出“内存不足”的消息,
要使用陷阱捕获(_set_new_handler(...)),见MSDN.
加载更多回复(3)
软件介绍: Cacheman是一款非常专业的系统缓存优化工具,它可以通过优化和控制缓存来达到提高电脑运行速度的目的。自动优化功能会检测你的系统并且自动将系统配置为最优状态,提高系统的性能和稳定性,建议在使用自动优化前请关闭其他所有正在运行的程序。你可以在高级配置中选择适合的优化模式:最佳配置:大多数台式计算机的最佳选择,此配置方案蕴含了超过10年的windows优化经验,它建立在众多计算机和用户分析报告的基础上,对计算机和系统无任何副作用,并将为每台计算机提供大幅的性能提升。最大稳定模式: 此配置方案以世界各地的配置反馈为基础,并适当添加了一些实验性优化模块以提供额外的性能提升。由于这些实验性调整中的部分功能缺乏对应的长期优化经验,所以此 案是喜欢测试和体验用户的最佳选择。最高稳定:此配置方案是为出于稳定因素而采用旧程序的计算机服务的。用以处理拙劣软件的宽限期、 容错能力和等候状态将会增加。请不要在稳定的计算机上使用此方案。笔记本/上网本模式:笔记本、上网本等移动设备的最佳通用配置,但也有一个显著的区别。此方案充分考虑到电池寿命和散热问题。游戏PC:此方案适合用于运行像电脑游戏等全屏幕应用程序的计算机。此配置文件通过优化以使后台任务和系统服务不会中断前台应用程序,特别是电脑游戏。游戏延迟和卡顿通常可由后台任务(如计算机病毒扫描) 产生。Cacheman 将确保游戏不会被拖慢。数字音频工作站: 数字音频工作站是设计用于录制和编辑数字音频的计算机。如果您选择此配置方案,Cacheman将优化windows 参数以尽量减少系统延迟并提高音频编辑的性能。高级用户: 此配置方案专为要完全控制计算机的用户而设计。来自用户帐户控制 (UAC)的警告消息将被禁用。Windows系统将由于优化而对编写拙劣的软件的耐受性下降,它将不能阻止其他正在运行的应用程序。网络服务器:  此配置方案适用于7X24小时不间断运行的系统,例如网络服务器和局域网文件服务器或互联网站点服务器。Windows 将为后台进程和长时间运行缓存而进行优化。windows7平板电脑:此配置方案可以提高华硕、三星以及联平板电脑界面响应速度。windows8平板电脑:用于提高许多windows8 x86/x64平板电脑的用户界面响应速度。
软件功能: 1、显著提高系统速度 2、专治各种低配置,小内存,提高速度biu biu biu ~ 3、限制程序内存使用率和CPU使用率以及优先级 4、有效降低硬盘读写频率(经常硬盘灯狂闪可得到解决) 5、更多牛逼功能自己挖掘 补充说明: 此款软件不同于360等之流的系统优化策略, 而是通过动态缓存的方法来有效提高系统速度, 并矫正大多数不健康的系统行为以及不正当操作[1], 优化过程并没有修改注册表和更改文件等操作,属于比较安全的 有些人说升级硬件才是王道,没错,对于硬件好的朋友用这个软件表面是没有感觉的 但它对于系统底层的正面作用是你感觉不到的, 比如硬盘灯狂闪,过度读写,不合理分配CPU资源等,参照上面[1]处, 这个软件可以改善你众多看不到的底层机理,除了改善速度还有延长硬件寿命的效果 所以不管你配置高不高这个软件都可以保驾护航 另外有朋友说用完出现反效果,我这可能是原初系统缺陷造成的 比如过度优化精简系统,电脑店装机系统等 还有就是软件冲突,比如系统常驻有其他优化软件 建议使用此软件时其他优化软件可以禁用或卸载哦 新手建议点自动优化后选“世界最佳”即可 具体请以自己使用习惯来优化, 比如你是玩游戏为主就选游戏方案 做设计的就选图形方案,搞视频的就选数字音频工作站方案,依此类推……

1,650

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 非技术类
社区管理员
  • 非技术类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧