为啥 Linux 32位 c++ 可以申请超过4G以上的内存

loud1984 2009-04-06 08:03:39
为啥 Linux 32位 c++ 可以申请超过4G以上的内存,并且我还测试过,把这个数字扩大到100G都可以申请成功,即使用虚拟内存(姑且说寻址可超过4G),硬盘都没有这么大。
代码基本上就是 :
long long length=5000000000ll;
char *p=new char[length];
if(!p) //判断成功与否
exit(1);

memset(p,48,length);
cout<<p[length-1]<<endl; //输出0
...全文
319 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
loud1984 2009-04-06
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 morris88 的回复:]
老兄,貌似你应该:

printf("%p\n", &p[length - 1]);
printf("%p\n", &p[f]);
[/Quote]
其实都差不多,我刚才试了,输出以下三项
printf("%p\n",&p[f]);
printf("%p\n",&p[0]);
printf("%p\n",&p[1]);
结果分别为:
0x93e29108
0x8decb008
0x8decb009
说明不是同一内容
threeleafzerg007 2009-04-06
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 loud1984 的回复:]
引用 3 楼 threeleafzerg007 的回复:
32位机器的话
进程虚地址空间 一般是
用户 3G 内核 1G
用户的 3G 除了1G 用于映射共享库外,自己也就2G了
所以一般堆的大小不超过2G
你这个比较怀疑。
可以 用 pmap pid 看一下进程地址空间 用图来说明。

确实一些资料和网络上是这样说,也符合我们的想法,但是不知这些东西是不是过时了,就像前几天,我做了一个实验,很多网上都说,windows下无法访问超过4G以上的文件用ifstream…
[/Quote]

多试试,呵呵。

打出指针地址

看看能 超过
0xc0000000(用户态下进程能产生和访问线性地址的极限。)吗?
morris88 2009-04-06
  • 打赏
  • 举报
回复
老兄,貌似你应该:

printf("%p\n", &p[length - 1]);
printf("%p\n", &p[f]);
loud1984 2009-04-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 threeleafzerg007 的回复:]
32位机器的话
进程虚地址空间 一般是
用户 3G 内核 1G
用户的 3G 除了1G 用于映射共享库外,自己也就2G了
所以一般堆的大小不超过2G
你这个比较怀疑。
可以 用 pmap pid 看一下进程地址空间 用图来说明。
[/Quote]
确实一些资料和网络上是这样说,也符合我们的想法,但是不知这些东西是不是过时了,就像前几天,我做了一个实验,很多网上都说,windows下无法访问超过4G以上的文件用ifstream类,但事实不是,ifstream的类型是pos_type 16字节的(不同系统 可能不同),可以访问很大很大的文件,他们的说法是以前的规则。
loud1984 2009-04-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 morris88 的回复:]

p是32bit的指针,p[length - 1]相当于 p += length - 1;当p > (2^32 - 1) 时,就会发生翻转,变成从 0 开始。那个 cout 输出不能代表什么?
[/Quote]
我做了如下的测试,
int main(void)
{
long long length=5000000000ll;
char *p=new char[length];
if(!p)
memset(p, 48, length);
long long f=4394967296ll;
p[f]=49;
cout < <p[f] < <endl; //为1
cout < <p[0] < <endl;//为0
cout < <p[1] < <endl;//为0
return 0;
}
按你的说法,p[0]和[f]的值都应该为1,担不是。不过你的说法,很有建设性。我也纳闷,已经超过指针的范围了。
loud1984 2009-04-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 morris88 的回复:]

p是32bit的指针,p[length - 1]相当于 p += length - 1;当p > (2^32 - 1) 时,就会发生翻转,变成从 0 开始。那个 cout 输出不能代表什么?
[/Quote]
我做了如下的测试,
int main(void)
{
long long length=5000000000ll;
char *p=new char[length];
if(!p)
memset(p, 48, length);
long long f=4394967296ll;
p[f]=49;
cout < <p[f] < <endl; //为1
cout < <p[0] < <endl;//为0
cout < <p[1] < <endl;//为0
return 0;
}
按你的说法,p[0]和[f]的值都应该为1,担不是。不过你的说法,很有建设性。我也纳闷,已经超过指针的范围了。
morris88 2009-04-06
  • 打赏
  • 举报
回复

int main(void)
{
long long length=5000000000ll;

char *p=new char[length];
if(!p)
memset(p, 48, length);
cout << p[length - 1] << endl;

return 0;
}


p是32bit的指针,p[length - 1]相当于 p += length - 1;当p > (2^32 - 1) 时,就会发生翻转,变成从 0 开始。那个 cout 输出不能代表什么?
threeleafzerg007 2009-04-06
  • 打赏
  • 举报
回复
32位机器的话
进程虚地址空间 一般是
用户 3G 内核 1G
用户的 3G 除了1G 用于映射共享库外,自己也就2G了
所以一般堆的大小不超过2G
你这个比较怀疑。
可以 用 pmap pid 看一下进程地址空间 用图来说明。
loud1984 2009-04-06
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 morris88 的回复:]
C/C++ codelonglonglength=5000000000ll;char*p=newchar[length];if(!p)//判断成功与否exit(1);

memset(p,48,length);
cout<<p[length-1]<<endl;//输出0

貌似这个不太可能,能否将汇编代码页贴上来?
[/Quote]这个肯定没问题,我都用过了。你如果有Linux系统可以试一下。我觉得“汇编代码”你不一定能看明白,这个确实是能的。
morris88 2009-04-06
  • 打赏
  • 举报
回复

long long length=5000000000ll;
char *p=new char[length];
if(!p) //判断成功与否
exit(1);

memset(p,48,length);
cout < <p[length-1] < <endl; //输出0


貌似这个不太可能,能否将汇编代码页贴上来?

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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