有没有办法模拟内存用完的情况?

THEBEST 2004-04-27 07:31:34
我总想让new申请内存不成功,
但它总成功.如果我把申请的对象搞成好大好大的对象数组的话程序会运行很慢
然后不会告诉你申请不到内存因为大家都知道一旦new失败时它会不停的试着申请的.
系统可能会死掉.
我现在就想有没有什么办法模拟申请不到内存呢?
系统:linux, windows.
...全文
50 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
陈硕 2004-05-12
  • 打赏
  • 举报
回复
如果你用 VC,还有一种办法是:

用 _CrtSetAllocHook 设置一个 hook :
int MyAllocHook( int allocType, void *userData, size_t size, int blockType,
long requestNumber, const unsigned char *filename, int lineNumber);

这样可以钩住new分配内存的动作,这时 blockType 是 _CLIENT_BLOCK 且 allocType 是 _HOOK_ALLOC,该函数返回FALSE表示分配失败。你可以记录分配的字节数,当字节数大于某值时,返回FALSE,就能模拟C++下内存用完的情况。google一下,就知道了。
xiaocai365 2004-05-11
  • 打赏
  • 举报
回复
有意思
fireseed 2004-05-09
  • 打赏
  • 举报
回复
to 楼主:

忘了说了,上面的代码就是你需要的“模拟内存用完的情况”,如果你哪里还有不明白的地方,就留言在这里或发短消息给我都可以,我很乐意和你还有大家讨论这个问题。
fireseed 2004-05-09
  • 打赏
  • 举报
回复
看一下<heapinit.c>里的代码:

……
int __cdecl _heap_init (
int mtflag
)
{
// Initialize the "big-block" heap first.
if ( (_crtheap = HeapCreate( mtflag ? 0 : HEAP_NO_SERIALIZE,
BYTES_PER_PAGE, 0 )) == NULL )
return 0;
……

HeapCreate的最后一个参数是0,表示该堆是可自增的,并把句柄放在_crtheap里


再看<malloc.c>里的代码:
void * __cdecl _heap_alloc_base (size_t size)

{
……
return HeapAlloc( _crtheap, 0, size );
……
}
这个函数是会被new调用的(debug编译),所以,我们只需要改变_crtheap的值就可以来模拟内存用光的情况。


/*以下代码在VC7.1中编译通过,并运行成功*/

// 包含windows头文件
#include <windows.h>
// 如果没有此宏定义,winheap将包含出错
#define _CRTBLD
// 包含winheap头文件,用于重写_crtheap变量
#include <..\crt\src\winheap.h>
// 包含水量
#include<new>
#include<iostream>
using namespace std;

// 为_crtheap指定外部链接
extern HANDLE _crtheap;
// 指定你需要模拟的最大可申请内存的量
#define MAX_MEMSIZE 4096

void __cdecl newhandler( )
{
cout << "The new_handler is called:" << endl;
throw bad_alloc( );
return;
}

int main( void )
{
// 设置new异常处理句柄
set_new_handler (newhandler);
// 将原先的堆句柄保存下来
HANDLE hOldHeap = _crtheap;
// 创建自己的堆
_crtheap = HeapCreate( HEAP_NO_SERIALIZE, 0, MAX_MEMSIZE );
//申请测试
char *p = NULL;
try
{
p = new char[MAX_MEMSIZE + 1];
}
catch ( exception e )
{
cout << e.what( ) << " xxx" << endl;
}
delete []p;

// 释放另申请的堆
HeapDestroy( _crtheap );
// 恢复原进程堆指针
_crtheap = hOldHeap;

system( "pause" );
return 0;
}



fireseed 2004-05-09
  • 打赏
  • 举报
回复
当然,每个进程都可以访问那“属于”它的2GB内存,尽管这些内存看起来是连续的,但实际上它的管理方式和硬盘的“簇”类似,它们在内部都被分割成了4K大小的单元,这个单元就是在任务管理器中见到的名词“页”。

某个进程需要访问某段物理内存时,需要经过一个Page Directory和Page Table,才能访问到Page Frame。当进程向系统申请内存时,系统会去Page Table中查找没有提交过的内存,然后将它们连接起来,当你申请的内存很大,但还不大于所有可用的内存量时(如果大于,将会立即返回错误),这个过程会非常慢。上面那位cgsw12345(cgsw)说的并不一无是处,但有一点需要强调的是:当连续申请并不太大的内存时,到某一程序,系统就很可能抛出错误。

在VC++的实现中,new使用的是HeapAlloc,它会向进程启动时建立的堆中划分出一块。进程启动时建立的块是可自增度的,所以当你new的内存超过当前堆的长度时,堆会有一个自增的操作,然后再满足进程的需求。
oyd 2004-05-08
  • 打赏
  • 举报
回复
对于32 位以上的应用程序而言,无论怎样使用
malloc 与new,几乎不可能导致“内存耗尽”。我在Windows 98 下用Visual C++编写了
测试程序.这个程序会无休止地运行下去,根本不会终止。因为32 位操作
系统支持“虚存”,内存用完了,自动用硬盘空间顶替。我只听到硬盘嘎吱嘎吱地响,
Window 98 已经累得对键盘、鼠标毫无反应。
我可以得出这么一个结论:对于32 位以上的应用程序,“内存耗尽”错误处理程序
毫无用处。这下可把Unix 和Windows 程序员们乐坏了:反正错误处理程序不起作用,
我就不写了,省了很多麻烦。
-------------------------------------------------------------------------------
这段话是不正确的,因为写这段话的人忽略了硬盘空间是有限的这个事实。
许多用户在用windows的时候,虚拟内存设置为固定大小,不让系统自己管理
许多用户的window目录所在的分区自由空间不大于2G
许多用户运行java程序时,动辄上百M虚拟内存,最惨的是程序员,一面用jbuilder调试自己的java程序,一面还要开一个tomcat和几个ie窗口来测试java程序,同时免不了要开个QQ\MSN聊天,还要在CSDN灌水,一不小心,虚拟内存就不够了。
iintsy 2004-05-08
  • 打赏
  • 举报
回复
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/specl_28.asp

是通过_set_new_handler 指定的函数的返回值来判断是否要在内存分配失败后继续尝试new的
iintsy 2004-05-08
  • 打赏
  • 举报
回复
struct DUMMY_NO_MEM_TAG {} no_mem;

void * operator new (size_t, DUMMY_NO_MEM_TAG)
{
throw std::bad_alloc("够不够神经病?");
}

int main()
{
try {char * p = new(no_mem) char[123];} // 这里应该不是数组吧。
catch(std::bad_alloc& e) {
std::cerr << e.what();
}
}

下面是new的重载:
class Blanks
{
public:
Blanks(){}
void *operator new( size_t stAllocateBlock, char chInit );
};
void *Blanks::operator new( size_t stAllocateBlock, char chInit )
{
void *pvTemp = malloc( stAllocateBlock );
if( pvTemp != 0 )
memset( pvTemp, chInit, stAllocateBlock );
return pvTemp;
}
int main()
{
Blanks *a5 = new( 0xa5 ) Blanks;

return a5 != 0;
}
前面的做法只是重载了new 操作符,屏蔽全局的new操作符,这样就可以达到模拟内存用完的情形了。


oxoxox 2004-05-08
  • 打赏
  • 举报
回复
将windows虚拟内存设置为0或者不设置虚拟内存.
THEBEST 2004-05-07
  • 打赏
  • 举报
回复
Wolf0403(完美废人)(期待有一天。。。)

....?
THEBEST 2004-05-04
  • 打赏
  • 举报
回复
TO:Wolf0403(完美废人)(期待有一天。。。)

struct DUMMY_NO_MEM_TAG {} no_mem;

void * operator new (size_t, DUMMY_NO_MEM_TAG)
{
throw std::bad_alloc("够不够神经病?"); //怎么说不能调用?我加了exception
}

int main()
{
//是调用 new(sizeof(char), no_mem);的意思吧?
try {char * p = new(no_mem) char[123];} // 这里应该不是数组吧。
catch (...) {}
}能解释一下吗?
THEBEST 2004-04-29
  • 打赏
  • 举报
回复
如果是用虚拟内存的话为什么char *p = new char[0x7FFFFFFF];这个又一下子就
throw了呢?
按理说它也不会抛出呀?
代码之诗 2004-04-29
  • 打赏
  • 举报
回复
0x7FFFFFFF 是 2G 内存,系统再牛也知道自己没那么多东东可用,所以……
Wolf0403 2004-04-29
  • 打赏
  • 举报
回复
struct DUMMY_NO_MEM_TAG {} no_mem;

void * operator new (size_t, DUMMY_NO_MEM_TAG)
{
throw std::bad_alloc("够不够神经病?");
}

int main()
{
try {char * p = new(no_mem) char[123];}
catch (...) {}
}
Wolf0403 2004-04-29
  • 打赏
  • 举报
回复
想跟电脑过不去还不简单?

while (true)
new char[numeric_limits<size_t>::max()];
THEBEST 2004-04-28
  • 打赏
  • 举报
回复
楼上的不错.
但是如何让系统不分配内存给你呢?:)

如果是用虚拟内存的话为什么char *p = new char[0x7FFFFFFF];这个又一下子就
throw了呢?
iintsy 2004-04-27
  • 打赏
  • 举报
回复
好像只能让系统不分配内存给你,这样好难哦,不会

系统有4G的内存供你用呢...
Areece 2004-04-27
  • 打赏
  • 举报
回复
写个你自己的new函数,然后在里面抛出std::bad_alloc
代码之诗 2004-04-27
  • 打赏
  • 举报
回复
……楼主的要求比较诡异,在下才疏学浅……
另待高人吧。
THEBEST 2004-04-27
  • 打赏
  • 举报
回复
以前看到过这段话.
但我想要的是模拟不是真正的发生.
不知可不可能?
加载更多回复(12)

65,206

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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