我有一个非常大的分子动力学C程序。它与N=10000粒子正确地工作。当我通过增加可变大小来增加粒子到N=100000时,它会产生一个分割错误。
我执行了ulimit -s unlimited并解决了问题。
Q1.是检查我的代码将使用多少堆栈内存、代码性能检查(优化)、内存泄漏的任何方法。
Q2.如果我的代码的结构类似,嵌套函数,
int main() {
function1();
return 0;
}
void function1() {
for(int i=0;i<1000;i++) {
function2();
}
}
void function2() {
double Var[100000];
}在for循环中使用function2()会比只执行一次更多堆栈内存吗?
发布于 2019-05-01 17:20:03
Q1。我想知道是否有任何方法来检查我的代码将使用多少堆栈内存、代码的性能检查(优化)、内存泄漏。
不怎么有意思。C标准甚至没有提到堆栈,任何C编译器都可以创建不使用堆栈且仍然符合C标准的二进制文件。
然而,在现实中,堆栈几乎总是被使用,并且开销非常小。只要把所有的局部变量加起来,你就会得到一个很好的估计。
不应预测性能。应该对其进行测量,然后在必要时进行优化。
编译器很难,即使不是不可能,也很难以可靠的方式检测内存泄漏。你可以使用类似的程序,如瓦兰。
Q2。如果我的代码的结构类似于嵌套函数,因为for循环中的function2调用,它会比只使用一次更多的堆栈内存吗?
不是的。每次调用function2()时,都会创建一个新的堆栈框架,其空间可容纳100000个双倍。但是,当函数返回时,它将立即释放。这里的问题不是在循环中调用函数。问题是在堆栈上分配巨大的数组,这可能会成为一个问题。您应该考虑动态地分配它们。基本上,看起来是这样的:
void function2
{
double *var = malloc(100000*sizeof(*var));
/* Code */
free(var);
}如果使用递归函数,堆栈可能会成为一个问题。让我们考虑这个求和函数,它将所有自然数之和到num:
unsigned long long sum(unsigned long long num)
{
if(num == 0) return num;
return num + sum(n-1);
}一个long long通常是8个字节,所以如果您将这个函数用于非常大的num (可能是100000或1000000),您可能会遇到堆栈问题。
发布于 2019-05-01 17:27:36
Q1.我想知道是否有任何方法来检查我的代码将使用多少堆栈内存、代码的性能检查(优化)、内存泄漏。
您可以通过分析调用图和每个函数中声明的变量来估计程序所需的堆栈空间,但对于一个复杂的程序来说,这并不容易。如果涉及到任何递归,则要困难得多,但至少应该能够放置一个粗略的上限。但是,简单的方法是测量在特征输入上运行时的使用情况。
绝对表现对人类来说是极其难以预测的。我们通常能做的最好的事情就是描述性能如何随着问题的大小而扩展。应始终衡量比较业绩。
至于内存泄漏,人工仔细的代码分析通常可以检测内存泄漏,但最好是通过使用运行时内存使用分析工具(如Val差尔)来补充。这类工具即使在分析良好的代码中也会出现漏洞,频率令人痛苦。
Q2.如果我的代码结构像,嵌套函数,.由于for循环中的function2调用,它会使用比只使用一次更多的堆栈内存吗?
不是的。当控制离开该函数时,将释放函数的自动分配资源。无论是在循环中还是在其他情况下,多次调用同一个函数都不会使用比最严格的单个调用更多的自动(堆栈)资源。
但是,当一个函数通过直接或间接调用自身进行递归时,它可能确实使用了与递归深度成比例的额外资源。我之所以说“可能”,是因为在某些情况下,编译器可能能够在单个函数调用中将递归转换为迭代。
发布于 2019-05-01 18:34:50
最好不要在堆栈上创建大型对象。相反,应该用C中的malloc或C++中的new动态地分配它们。
如果分配请求被程序拒绝,您的程序就可以恢复。
通过在C++中使用新的智能指针,您可以帮助确保释放所有分配并且不发生泄漏,否则您只需“仔细编写代码”,这是C编程的缺点。
https://stackoverflow.com/questions/55939740
复制相似问题