【问题标题】:Different behaviours of "New" operator - Dynamic memory allocation“New”操作符的不同行为——动态内存分配
【发布时间】:2014-08-01 05:05:38
【问题描述】:

我在嵌入式设备中使用简单的内存分配程序测试了一个示例 try-catch 块,该设备仅使用 64MB RAM 和定制的 linux OS 32 位 Xscale Arm 架构运行。我的目的是验证正常的 try-catch 块是否会当此设备上没有内存时工作。我列出的代码如下。假设这是程序1。

#include "stdio.h"
#include "stdlib.h"
int main()
{
    int count;
    int *q[409600];
    printf("\nHeap Leak Starting at..");
    system("date");
    fflush(stdout);
    printf("\n, Count is located at ,%p,",&count);
    for(count=0;count<409600;count++)
    {
            printf("\nCount = ,%d,",count);
            int i=2;
            try
            {
                    fflush(stdout);
                    q[count] = new int[409600];
                    printf("New Success.Allocated %ld Bytes at %p.Difference = 0x%x,\n",(i*100000),q[count],(long)(&i) - (long)q[count]);
                    fflush(stdout);
            }
            catch(...)
            {
                            printf("\nException Caught...New Failed..No Memory Available.\n");
                            fflush(stdout);
                            exit(1);
            }
    }
}

Program1 的输出:

Thu Jul 31 20:38:00 UTC 2014
Heap Leak Starting at..,

Count is located at ,0xbffffc48,

Count = ,0,New Success.Allocated 200000 Bytes at 0x402c0008.Difference = 0x7fbafc3c,

Count = ,1,New Success.Allocated 200000 Bytes at 0x40451008.Difference = 0x7fa1ec3c,

Count = ,2,New Success.Allocated 200000 Bytes at 0x405e2008.Difference = 0x7f88dc3c,

Count = ,3,New Success.Allocated 200000 Bytes at 0x40773008.Difference = 0x7f6fcc3c,

........The count goes on........

Count = ,1954,New Success.Allocated 200000 Bytes at 0xbf854008.Difference = 0x61bc3c,

Count = ,1955,New Success.Allocated 200000 Bytes at 0xbf9e5008.Difference = 0x48ac3c,

Count = ,1956,New Success.Allocated 200000 Bytes at 0xbfb76008.Difference = 0x2f9c3c,

Count = ,1957,
Exception Caught...New Failed..No Memory Available.

现在这是一个预期的行为。由于没有内存,抛出异常。

然后我将“q[count] = new int[409600]”这一行修改为“q[count] = new int[100000]”。假设这是program2。我重新编译了程序并在同一设备上执行.

程序2的输出:

Thu Jul 31 20:39:43 UTC 2014

Heap Leak Starting at..,

Count is located at ,0xbffffc48,

Count = ,0,New Success.Allocated 200000 Bytes at 0x402c0008.Difference = 0x7fbafc3c,

Count = ,1,New Success.Allocated 200000 Bytes at 0x40322008.Difference = 0x7fb4dc3c,

Count = ,2,New Success.Allocated 200000 Bytes at 0x40384008.Difference = 0x7faebc3c,

Count = ,3,New Success.Allocated 200000 Bytes at 0x403e6008.Difference = 0x7fa89c3c,

............The count goes on.............

Count = ,5215,New Success.Allocated 200000 Bytes at 0x87d00018.Difference = 0x3816fc2c,

Count = ,5216,New Success.Allocated 200000 Bytes at 0x87d61aa0.Difference = 0x3810e1a4,

Count = ,5217,New Success.Allocated 200000 Bytes at 0x87e00018.Difference = 0x3806fc2c,

Count = ,5218,New Success.Allocated 200000 Bytes at 0x87e61aa0.Difference = 0x3800e1a4,

Count = ,5219,New Success.Allocated 200000 Bytes at 0x87f00018.Difference = 0x37f6fc2c,

Count = ,5220,

此时,该进程在 New 操作员处永远挂起。即使我在后台运行该进程,我也无法访问终端。

现在我对注意到new 的这种不同行为感到困惑。请注意,在抛出异常的情况下,我分配的大小(409600)比进程挂起的情况(100000)大。有人可以帮我澄清New 的这种不同行为吗?请分享您的想法和一些线索,因为我需要这一突破才能调试同一设备中报告的验证错误。

PS:忽略号码200000,因为我打错了。

【问题讨论】:

  • 一方面,您有 C++ 规范,它告诉您new 在无法分配内存时会抛出异常。另一方面,当系统内存不足时,Linux 内核会随机终止进程。
  • 嗨@JoachimPileborg:你的意思是内核在内存不足时会杀死这个进程吗?即当以 100000 运行时?而当使用 409600 运行时它不会杀死?
  • 内核可以在系统内存不足时杀死进程,但不一定是导致问题的进程,Linux内核内存不足处理程序以杀死而闻名随机处理
  • @JoachimPileborg :如果是这样,为什么控制台/设备会进入无响应状态?因为使用控制台我可以找到进程列表还活着..在这种情况下,如果系统挂起..它需要强制重启..

标签: c++ linux memory memory-management


【解决方案1】:

printffflush 例程可能正在尝试分配内存。他们也可能正在锁定或执行一些其他导致死锁的同步。分配异常对象可能需要内存(尽管希望任何自尊的运行时都能处理这种情况)。

当没有剩余内存时,大多数 C 库调用的行为可能没有很好地指定(可能它们死锁或进入循环,或者它们留下一些损坏的东西,因此当您的“catch”尝试打印时,它会死锁)。大多数库没有明确定义的语义来说明它们在内存不足时的行为(或者即使它们需要使用任何内存)。

附加调试器或获取回溯以查看您的进程挂起/等待的位置。

或者,您可以使用在其实现中不太可能分配任何内存的 API 调用来检验我的假设:

  • exit 有助于识别代码的哪一部分退出(传递不同的数字)
  • write 通常是免分配的(但很难传递运行时字符串)。类似:write(1, "I am here", strlen("I am here"));(直接写入调用后无需刷新。)

【讨论】:

  • 嗨 P.T,你是说 gdb 吗?
猜你喜欢
  • 2018-02-04
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 2018-06-16
  • 2023-04-06
  • 1970-01-01
相关资源
最近更新 更多