免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4743 | 回复: 9
打印 上一主题 下一主题

[Linux] 请教一个C/C++ 内存问题,动态new,奇怪现象 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-07-22 11:33 |只看该作者 |倒序浏览
本帖最后由 InMySin 于 2012-07-22 11:45 编辑

论坛之前有类似帖子,但是回复我还是搞不懂,于是自己动手写了写:
好啦,问题来了,我这个程序在无限循环地申请内存,每次申请应该为 10000000*4 byte( 为了内存管理而增加的一点开销暂时不管),
g++ -Wall crapp.cpp -o crapp  编译通过,有点警告,主要是为了输出地址,使用%u 应该是正确的,%d会出现负数?

然后./crapp 运行

我开始以为这个程序由于不断申请内存,导致系统内存不足,然后想观察下发生什么情况:),我每次运行前都free -m 一下:
                   total         used       free     shared    buffers     cached
Mem:          1759       1437        321          0        126        417
-/+ buffers/cache:       893        866
Swap:         1035          0       1035

内存可用也就是321MB左右,这样我申请的应该很快把这个321内存用光,但是实际是:运行程序后,我不断free -m 可用内存却几乎没有大的变化,程序最终
new失败而core dump;

程序输出:
./crapp
Stack is 3213834968  ---》 大概可以看到main里面的局部变量 分配位置,用bc(我用bc算错了,改成octave)算一算,真的在3G 左右,不是我在操作系统里面认为那样,每个进程4G逻辑空间,stack栈应该在顶层,也就是4G左右的地方,这个与我之前看法完全不同;

New 4m 0
The p=3038351368
New 4m 1
The p=2998349832
New 4m 2
The p=2958348296
New 4m 3
The p=2918346760     -》》》在heap堆上的内存,上网找找好像说超过128K,堆是往下增长,而不是往上增长的?? 之前看linux program的书都是堆在地址低地方不断向上增长,但是这又个我之前看法不同!


最重要是,这些都能分配成功了,一次大概40M,free -m 中used free几乎没有变化,难道我不写内核就只是帮我记录一下分配空间,但是并不是实际分配物理内存??


最后,这个程序不能搞崩溃OS,都是这样被杀掉了:
New 4m 77
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

但是同学们跑时候首先sync好,关闭一些重要程序拉,,求知道
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>

  4. using namespace std;

  5. int main( int argc , char ** argv )
  6. {
  7.     int * p;
  8.     int cnt;

  9.     cnt = 0;

  10.     printf("Stack is %u\n" , &p );
  11.     while( true )
  12.     {
  13.         sleep( 1 );

  14.         fprintf( stderr , "New 4m %d\n" , cnt++);
  15.         p = new int[10000000];

  16.         p[888888] = 124;

  17.         fprintf( stderr , "The p=%u\n" , p );


  18.     }

  19.     return 0;
  20. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2012-07-22 11:36 |只看该作者
还有系统一些信息:
Linux df 2.6.35.14-106.fc14.i686 #1 SMP Wed Nov 23 13:57:33 UTC 2011 i686 i686 i386 GNU/Linux

ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 13974
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

论坛徽章:
1
天蝎座
日期:2013-12-06 18:23:58
3 [报告]
发表于 2012-07-22 18:30 |只看该作者
系统有过载自我保护功能,不会让你这么无限的malloc的,超过极限就失败了,

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
4 [报告]
发表于 2012-07-23 13:29 |只看该作者
InMySin 发表于 2012-07-22 11:33
最重要是,这些都能分配成功了,一次大概40M,free -m 中used free几乎没有变化,难道我不写内核就只是帮我记录一下分配空间,但是并不是实际分配物理内存??

你分配到的始终都是虚拟内存,物理内存是 OS 在管理。

最后,这个程序不能搞崩溃OS,都是这样被杀掉了:
New 4m 77

这样就能被搞崩溃的 OS 是不是太脆弱了点?另外,算算 40 * 77 大概是多少。

论坛徽章:
0
5 [报告]
发表于 2012-07-23 15:07 |只看该作者
现代OS大部分设计成内核与用户位于同一地址空间。也是就是说,4G的虚拟地址里,内核要占用一部分。

分配线性地址而不分配物理内存,完全合理,甚至大部分情况下是常态。这是两种不同的资源,前者是per-process的,后者是整个系统的,OS不一定会成对分配,这就是所谓的page on demand。分配线性地址时,OS只是做个标记,并没为其安排物理内存。真正访问这个地址时,硬件发现这个地址下没有对应物理内存,产生page fault,OS处理这个错误时,发现承诺过给这个地址一块内存,继而系统中为其分配资源。用户态访问这个地址的整个过程中,完全看不到内核这一系列动作。

论坛徽章:
0
6 [报告]
发表于 2012-07-23 16:38 |只看该作者
回复 4# MMMIX


    恩恩,昨天看了相关资料,大概明白,malloc/new 得到还是地址空间的内存,实际上的物理内存是内核做了映射,而这些物理内存可能是按需分配的,我不访问它就不用分配。。。

40*77 = 3080; 也跟网上说的 32位, 1G 内核空间,3G的用户空间,我把3G的用户空间的地址都用光了,所以再在3G的地址内malloc就肯定失败了。。

论坛徽章:
0
7 [报告]
发表于 2012-07-23 16:44 |只看该作者
回复 5# g__gle


    看了linux地址空间/内存布局等,明白你在说什么了,但是有个问题是,我通过 malloc 申请的一个 固定大小的 内存块(例如 40M),这些地址是连续的,但是映射都物理内存上就可能不是连续了,这40M的地址可能是OS东凑西凑拼起来了,还是一定有个40M大小的块?? 我认为应该是用页拼起来的,但是页可能不连续。。

论坛徽章:
0
8 [报告]
发表于 2012-07-25 22:54 |只看该作者
我觉得是用页拼凑起来的!内存管理程序通过映射机制把用户程序的逻辑地址映射到物理地址,对于你用malloc申请的连续的堆,你的访问每次都需要mmu 将逻辑地址转换成物理地址,如果发现程序中要用的虚地址没有对应的物理内存时,就发出了请页要求(当然页要求是连续的),程序要两种机制保证可以 满足1.内存的分配与回收!2.交换地址 保证页连续!

论坛徽章:
0
9 [报告]
发表于 2012-07-31 14:28 |只看该作者
我在centos上试了下,先用掉内存的空间,然后采用交换空间的,但让我迷惑的是,不管我申请多少空间,内存空间会马上用完。有知道是怎么回事的吗?

论坛徽章:
0
10 [报告]
发表于 2012-10-15 09:07 |只看该作者
这个与具体的系统有关,我在ubuntu下测试与楼主结果一样,但在windows下测试,则显示很快耗尽物理内存了。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP