计算内存使用量?

时间:2011-03-05 05:14:36

标签: c++ memory-management

让我们考虑以下因子:

#include <iostream.h>

int factorial(int);

void main(void) {
    int number;

    cout << "Please enter a positive integer: ";
    cin >> number;
    if (number < 0)
        cout << "That is not a positive integer.\n";
    else
        cout << number << " factorial is: " << factorial(number) << endl;
}

int factorial(int number) {
    int temp;

    if(number <= 1) return 1;

    temp = number * factorial(number - 1);
    return temp;
}

如何计算使用函数 factorial()的内存?更准确地说,我想知道函数使用了多少内存?

修改

这只是一个示例程序,我正在处理的程序有很多不同,并且有很多功能,我实际上想要计算每个函数的内存使用情况。

6 个答案:

答案 0 :(得分:4)

由于该函数仅使用堆栈内存,因此您可以在temp之前将return 1的地址存储在全局变量中,并将其与number的地址进行比较:

#include <iostream.h>

int factorial(int);

void* tos;

void main(void) {
    int number;

    cout << "Please enter a positive integer: ";
    cin >> number;
    if (number < 0)
        cout << "That is not a positive integer.\n";
    else
        cout << number << " factorial is: " << factorial(number) << endl;

    cout << "factorial used " << ((char*)&number - (char*)tos) << " bytes of stack.\n";
}

int factorial(int number) {
    int temp;

    if(number <= 1) {
        tos = &temp;
        return 1;
    }

    temp = number * factorial(number - 1);
    return temp;
}

答案 1 :(得分:3)

对于我的第二个答案(由我的第一个答案的评论提示),您可以使用一个函数来计算已触摸的堆栈数量。这是一个希望不会对给定架构上的堆栈性质做出太多假设的假设。它假设下降堆栈,这对大多数人来说是相当安全的选择:

#define LU_RAND_SEED 123456789LU
#define LU_RAND(S) ((S) * 69069 + 362437 & 0XFFFFFFFFLU)

int depth(int maxdepth)
{
  unsigned long r = LU_RAND_SEED;
  int d = 0;
  unsigned long *stk = (unsigned long *)alloca(maxdepth);
  for (int i = maxdepth/sizeof(unsigned long); i--; )
    {
      r = LU_RAND(r);
      if (stk[i] != r)
        {
          stk[i] = r;
          d = i;
        }
    }
  return maxdepth - d*sizeof(unsigned long);
}

在您要测试的功能之前调用一次,之后调用一次。第二个调用将返回已触摸的堆栈字节数(减去一些您必须通过实验确定的常量值)。您必须确保只有您正在测试的代码在两次调用depth()之间运行:

depth(512<<10);
int f = factorial(number);
int d = depth(512<<10);
cout << ... f ...

您还必须注意边缘情况。例如,如果number为0或1,则深度测试失败的原因我尚未弄清楚。善良知道如果编译器开始重用堆栈槽会发生什么。简而言之: caveat emptor

注意:

  1. 不言而喻,这种技术具有概率性。如果您的函数恰好使用与PRNG相同的数据填充堆栈的全部或部分,结果可能会受到影响,尽管超过几个字节的概率很小。
  2. 我从here解除了PRNG。 srand() / rand()或他们的线程安全对手可能会正常工作,但我想避免调用alloca()以外的任何函数。
  3. unsigned long r = (unsigned long)&r;避免了常量种子的稍微随机性,并且它起作用,因为如果对depth()的两次调用是在不同的堆栈深度进行的,那么这种技术无论如何都会失败。我只是不知道这样生成的种子会有多安全。

答案 2 :(得分:2)

使用分析工具 http://code.google.com/p/google-perftools/

或valgrind

答案 3 :(得分:0)

如果您不知道“阶乘”将有多少递归,则无法确定它将消耗多少内存。在32位机器上,此函数的1次递归应消耗8个字节(返回地址为4个字节,参数为4个字节)

答案 4 :(得分:0)

查看编译器生成的映射文件。这将显示所有尺寸。

答案 5 :(得分:0)

  1. 计算最大通话深度。 (应在任何算法分析课程中涵盖)

  2. 查找每次调用的堆栈使用情况(查看函数的汇编代码,不要忘记查阅CPU架构手册以了解call指令在堆栈上放置了多少数据。

  3. 查找每次调用的动态内存使用情况,查找mallocrealloc,C ++运算符new等函数以及std::vector等容器类。

  4. 乘法。