关于Windows 内存问题

szn_409 2018-03-01 10:10:10
前提:32位程序
我用vs2010 指定了 是 (/LARGEADDRESSAWARE)选项,则可以接近malloc 4GB,然后我还能用 CreateEvent 生成100万个内核对象,这里 我有2个问题

1.为什么在我 malloc 接近4GB内存后,还能 创建 100 万个 内核对象?难道内核对象不占用内存吗?

2.在我开启(/LARGEADDRESSAWARE)选项后并malloc 接近4GB内存后,内核模式分区不是都没地址了么,为什么程序还能正常?
...全文
721 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2018-03-06
  • 打赏
  • 举报
回复
引用 18 楼 szn_409 的回复:
[quote=引用 16 楼 zhao4zhong1 的回复:] 也没准你是64位电脑。
是64位的电脑,但是是32位的程序[/quote] 百度搜“32位程序在32位电脑和64位电脑上运行时内存管理的区别”
szn_409 2018-03-06
  • 打赏
  • 举报
回复
引用 19 楼 zhao4zhong1 的回复:
[quote=引用 18 楼 szn_409 的回复:] [quote=引用 16 楼 zhao4zhong1 的回复:] 也没准你是64位电脑。
是64位的电脑,但是是32位的程序[/quote] 百度搜“32位程序在32位电脑和64位电脑上运行时内存管理的区别”[/quote] 试过了 查了 msdn 资料 ,得到了满意的答案 谢谢
赵4老师 2018-03-05
  • 打赏
  • 举报
回复
malloc返回成功,不代表真正可用,你可以试试将malloc成功的后的每个字节赋值为0xFF,看会不会导致内存不足错误。
paschen 2018-03-05
  • 打赏
  • 举报
回复
引用 7 楼 szn_409的回复:
[quote=引用 5 楼 paschen 的回复:] /LARGEADDRESSAWARE下最多也就3G出头一点,到不了4G
但是我32位程序下 确实 malloc 了 接近4GB内存 并且 ,请看下面代码

	MEMORYSTATUSEX MemoryInfo = {};
	MemoryInfo.dwLength = sizeof MemoryInfo;
	GlobalMemoryStatusEx(&MemoryInfo);
	
	char buff[1024] = {};
	sprintf_s(buff, "系统已使用的物理内存百分比:%d%%, 系统实际物理内存(字节):%lld, 系统实际可用内存(字节):%lld, 系统页文件大小(字节):%lld, 系统可用页文件大小(字节):%lld, "
		"当前进程用户模式分区大小(字节):0x%llX, 当前进程虚拟地址空间中未保留和未提交的量(字节):%lld", MemoryInfo.dwMemoryLoad, MemoryInfo.ullTotalPhys, MemoryInfo.ullAvailPhys, 
		MemoryInfo.ullTotalPageFile, MemoryInfo.ullAvailPageFile, MemoryInfo.ullTotalVirtual, MemoryInfo.ullAvailVirtual);

	/*
	否 (/LARGEADDRESSAWARE:NO):
	系统已使用的物理内存百分比:40%, 系统实际物理内存(字节):8524783616, 系统实际可用内存(字节):5046480896, 系统页文件大小(字节):17047678976, 系统可用页文件大小(字节):13249622016, 
	当前进程用户模式分区大小(字节):0x7FFE0000, 当前进程虚拟地址空间中未保留和未提交的量(字节):2134200320

	是 (/LARGEADDRESSAWARE):
	系统已使用的物理内存百分比:41%, 系统实际物理内存(字节):8524783616, 系统实际可用内存(字节):5017403392, 系统页文件大小(字节):17047678976, 系统可用页文件大小(字节):13203300352, 
	当前进程用户模式分区大小(字节):0xFFFE0000, 当前进程虚拟地址空间中未保留和未提交的量(字节):4281683968
	*/
当开启了 /LARGEADDRESSAWARE 后,当前进程的用户模式分区大小确实达到了 0xFFFE0000 也差不多是4GB的大小了 [/quote] 内核对象内存布局安排方式只有微软知道,但可以肯定的是,设置/LARGEADDRESSAWARE的,肯定会限制了内核可用的地址空间,从而限制系统所能创建的线程等资源的数量,能创建的资源肯定比非大内存时的要少。我记得《Windows核心编程》上对此也进行了详细描述
szn_409 2018-03-05
  • 打赏
  • 举报
回复
引用 16 楼 zhao4zhong1 的回复:
也没准你是64位电脑。
是64位的电脑,但是是32位的程序
szn_409 2018-03-05
  • 打赏
  • 举报
回复
引用 15 楼 amoyman 的回复:
临时文件中(打漏了“文件”两个字)
其实我讨论的主要问题不是内存不足的问题,而是在32位程序的情况下,用户地址空间已经占了 4 字节所能表示的内存范围,此时内核地址空间是如何分布的,以及此情况下系统如何维护这个32位的进程
赵4老师 2018-03-05
  • 打赏
  • 举报
回复
也没准你是64位电脑。
阿麦 2018-03-05
  • 打赏
  • 举报
回复
临时文件中(打漏了“文件”两个字)
阿麦 2018-03-05
  • 打赏
  • 举报
回复
现在的windows很少出现“内存不足”了,据说是在操作系统方面采用文件交换的方法,申请的内存空间,并不一定有物理内存对应着,可能被保存在一个临时中。
szn_409 2018-03-05
  • 打赏
  • 举报
回复
引用 8 楼 paschen 的回复:
[quote=引用 7 楼 szn_409的回复:][quote=引用 5 楼 paschen 的回复:] /LARGEADDRESSAWARE下最多也就3G出头一点,到不了4G
但是我32位程序下 确实 malloc 了 接近4GB内存 并且 ,请看下面代码

	MEMORYSTATUSEX MemoryInfo = {};
	MemoryInfo.dwLength = sizeof MemoryInfo;
	GlobalMemoryStatusEx(&MemoryInfo);
	
	char buff[1024] = {};
	sprintf_s(buff, "系统已使用的物理内存百分比:%d%%, 系统实际物理内存(字节):%lld, 系统实际可用内存(字节):%lld, 系统页文件大小(字节):%lld, 系统可用页文件大小(字节):%lld, "
		"当前进程用户模式分区大小(字节):0x%llX, 当前进程虚拟地址空间中未保留和未提交的量(字节):%lld", MemoryInfo.dwMemoryLoad, MemoryInfo.ullTotalPhys, MemoryInfo.ullAvailPhys, 
		MemoryInfo.ullTotalPageFile, MemoryInfo.ullAvailPageFile, MemoryInfo.ullTotalVirtual, MemoryInfo.ullAvailVirtual);

	/*
	否 (/LARGEADDRESSAWARE:NO):
	系统已使用的物理内存百分比:40%, 系统实际物理内存(字节):8524783616, 系统实际可用内存(字节):5046480896, 系统页文件大小(字节):17047678976, 系统可用页文件大小(字节):13249622016, 
	当前进程用户模式分区大小(字节):0x7FFE0000, 当前进程虚拟地址空间中未保留和未提交的量(字节):2134200320

	是 (/LARGEADDRESSAWARE):
	系统已使用的物理内存百分比:41%, 系统实际物理内存(字节):8524783616, 系统实际可用内存(字节):5017403392, 系统页文件大小(字节):17047678976, 系统可用页文件大小(字节):13203300352, 
	当前进程用户模式分区大小(字节):0xFFFE0000, 当前进程虚拟地址空间中未保留和未提交的量(字节):4281683968
	*/
当开启了 /LARGEADDRESSAWARE 后,当前进程的用户模式分区大小确实达到了 0xFFFE0000 也差不多是4GB的大小了 [/quote] 内核对象内存布局安排方式只有微软知道,但可以肯定的是,设置/LARGEADDRESSAWARE的,肯定会限制了内核可用的地址空间,从而限制系统所能创建的线程等资源的数量,能创建的资源肯定比非大内存时的要少。我记得《Windows核心编程》上对此也进行了详细描述[/quote] 你说的没错, 我是看了 《Windows核心编程》 第十三章 才产生的问题, 设置了 那个 开关 确实限制了 内核可用的地址空间,但是从 GlobalMemoryStatusEx 返回的情况来看, 内核地址空间已经剩下 很小很小了,系统如何使用这么小的内核地址空间 来正常的维护我这个进程呢
szn_409 2018-03-05
  • 打赏
  • 举报
回复
引用 10 楼 xiaohuh421 的回复:
除了物理内存, 还有虚拟内存得嘛, 物理内存不足的时候, 会分配虚拟内存. 虽然申请的内存, 但这些内存如果没有被用到时, 会被切换到虚拟内存, 一般是磁盘中. 所以你电脑内存使用完了, 程序仍然能正常工作, 只是可能会比较卡.
我现在的问题 不是内存不足的问题,而是 用户地址空间 能访问接近4GB 此时内核模式空间基本被压榨完了 程序还能正常,我是疑惑这个问题
szn_409 2018-03-05
  • 打赏
  • 举报
回复
引用 9 楼 zhao4zhong1 的回复:
malloc返回成功,不代表真正可用,你可以试试将malloc成功的后的每个字节赋值为0xFF,看会不会导致内存不足错误。
看3楼 代码 ,我对分配的内存 已经访问了一遍 并没有出错
xiaohuh421 2018-03-05
  • 打赏
  • 举报
回复
除了物理内存, 还有虚拟内存得嘛, 物理内存不足的时候, 会分配虚拟内存. 虽然申请的内存, 但这些内存如果没有被用到时, 会被切换到虚拟内存, 一般是磁盘中. 所以你电脑内存使用完了, 程序仍然能正常工作, 只是可能会比较卡.
szn_409 2018-03-04
  • 打赏
  • 举报
回复
引用 5 楼 paschen 的回复:
/LARGEADDRESSAWARE下最多也就3G出头一点,到不了4G
但是我32位程序下 确实 malloc 了 接近4GB内存 并且 ,请看下面代码

	MEMORYSTATUSEX MemoryInfo = {};
	MemoryInfo.dwLength = sizeof MemoryInfo;
	GlobalMemoryStatusEx(&MemoryInfo);
	
	char buff[1024] = {};
	sprintf_s(buff, "系统已使用的物理内存百分比:%d%%, 系统实际物理内存(字节):%lld, 系统实际可用内存(字节):%lld, 系统页文件大小(字节):%lld, 系统可用页文件大小(字节):%lld, "
		"当前进程用户模式分区大小(字节):0x%llX, 当前进程虚拟地址空间中未保留和未提交的量(字节):%lld", MemoryInfo.dwMemoryLoad, MemoryInfo.ullTotalPhys, MemoryInfo.ullAvailPhys, 
		MemoryInfo.ullTotalPageFile, MemoryInfo.ullAvailPageFile, MemoryInfo.ullTotalVirtual, MemoryInfo.ullAvailVirtual);

	/*
	否 (/LARGEADDRESSAWARE:NO):
	系统已使用的物理内存百分比:40%, 系统实际物理内存(字节):8524783616, 系统实际可用内存(字节):5046480896, 系统页文件大小(字节):17047678976, 系统可用页文件大小(字节):13249622016, 
	当前进程用户模式分区大小(字节):0x7FFE0000, 当前进程虚拟地址空间中未保留和未提交的量(字节):2134200320

	是 (/LARGEADDRESSAWARE):
	系统已使用的物理内存百分比:41%, 系统实际物理内存(字节):8524783616, 系统实际可用内存(字节):5017403392, 系统页文件大小(字节):17047678976, 系统可用页文件大小(字节):13203300352, 
	当前进程用户模式分区大小(字节):0xFFFE0000, 当前进程虚拟地址空间中未保留和未提交的量(字节):4281683968
	*/
当开启了 /LARGEADDRESSAWARE 后,当前进程的用户模式分区大小确实达到了 0xFFFE0000 也差不多是4GB的大小了
paschen 2018-03-04
  • 打赏
  • 举报
回复
/LARGEADDRESSAWARE下最多也就3G出头一点,到不了4G
赵4老师 2018-03-03
  • 打赏
  • 举报
回复
搜“毛德操 windows内存管理”
赵4老师 2018-03-02
  • 打赏
  • 举报
回复
百度搜“内存延迟申请”
赵4老师 2018-03-02
  • 打赏
  • 举报
回复
容量大小从小到大:栈≤全局数据≤堆≤文件≤硬盘≤磁盘阵列≤云存储 当程序需要使用比如2GB~1TB左右的存储时,最简单的办法恐怕得是用文件读写模拟内存读写了吧。windows参考_fseeki64函数,linux参考fseeko64函数。
FILE *fA;fA=fopen("A","rb+");_fseeki64(fA,10000000000i64*sizeof(int),SEEK_SET);fputc(fA,0);//int A[10000000000];
int B;
_fseeki64(fA,9999999999i64*sizeof(int),SEEK_SET);fread(&B,1,sizeof(int),fA);//B=A[9999999999];
_fseeki64(fA,9999999999i64*sizeof(int),SEEK_SET);fwrite(&B,1,sizeof(int),fA);//A[9999999999]=B;
fclose(fA);
szn_409 2018-03-02
  • 打赏
  • 举报
回复
引用 2 楼 zhao4zhong1 的回复:
百度搜“内存延迟申请”
Debug跑的 内存确实分配到了,任务管理器里也能看出来 我主要困惑的地方是 当开启了 /LARGEADDRESSAWARE开关 用户模式下确实得到了接近4GB的内存,那么进程的内核模式分区 不是都被占用完了么,那么为什么进程还能正常运行

#include <Windows.h>
#include <new>
#include <process.h>
#include <vector>

using std::vector;
using std::nothrow;

DWORD __stdcall FunThread(void* pVoid)
{
	return 0;
}

int main()
{
	vector<char*> vecAlloc;
	while(1)
	{
		auto pRe = (char*)malloc(1024 * 1024);
		if (!pRe)
		{
			break;
		}

		vecAlloc.emplace_back(pRe);
		if (vecAlloc.size() > 3800)
		{
			break;
		}
	}

	std::reverse(vecAlloc.begin(), vecAlloc.end());
	auto nPoint = *vecAlloc.begin();
	size_t nMemorySize = vecAlloc.size();	

	vector<HANDLE> vecHandle;
	while(1)
	{
		HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
		if (hEvent == NULL || hEvent == INVALID_HANDLE_VALUE)
		{
			break;
		}
		vecHandle.emplace_back(hEvent);
		if (vecHandle.size() > 1000000)
		{
			break;
		}
	}
	size_t nHandleSize = vecHandle.size();	

	vector<HANDLE> vecThread;
	while(1)
	{
		HANDLE hThread = CreateThread(NULL, 0, FunThread, NULL, CREATE_SUSPENDED, nullptr);
		if (!hThread)
		{
			break;
		}
		vecThread.emplace_back(hThread);
		if (vecThread.size() > 1000000)
		{
			break;
		}
	}
	size_t nThreadSize = vecThread.size();	

	for (size_t i = 0; i < vecAlloc.size(); ++i)
	{
		memset(vecAlloc[i], 10, 1024 * 1024);			//访问内存不会出错
	}

	for (size_t i = 0; i < vecHandle.size(); ++i)
	{
		SetEvent(vecHandle[i]);							//内核对象均能触发成功
		WaitForSingleObject(vecHandle[i], INFINITE);
	}

	/*
		Win32开启 /LARGEADDRESSAWARE 开关
		0xfe800040
		nMemorySize = 3801
		nHandleSize = 1000001
		nThreadSize = 12
	*/

	printf("\n");
}

15,471

社区成员

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

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