首页 文章

内存泄漏C.

提问于
浏览
45

我刚刚在C中编写了一个代码进行字符串操作的代码,但是当我运行valgrind时,它显示了一些可能的内存泄漏 . 调试代码到粒度级我写了一个简单的C程序,看起来像:

#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
        std::string myname("Is there any leaks");
        exit(0);
}

并运行valgrind我得到:

==20943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 26 from 1)
==20943== malloc/free: in use at exit: 360,645 bytes in 12,854 blocks.
==20943== malloc/free: 65,451 allocs, 52,597 frees, 2,186,968 bytes allocated.
==20943== For counts of detected errors, rerun with: -v
==20943== searching for pointers to 12,854 not-freed blocks.
==20943== checked 424,628 bytes.
==20943== 
==20943== LEAK SUMMARY:
==20943==    definitely lost: 0 bytes in 0 blocks.
==20943==      possibly lost: 917 bytes in 6 blocks.
==20943==    still reachable: 359,728 bytes in 12,848 blocks.
==20943==         suppressed: 0 bytes in 0 blocks.
==20943== Reachable blocks (those to which a pointer was found) are not shown.
==20943== To see them, rerun with: --show-reachable=yes

然后让我感到震惊的是我们已经强行退出(我也用我原来的C代码执行) . 现在的问题是我想退出程序,因为我以前的旧代码等待新代码的退出状态 . 例如,二进制a.out等待b.out的退出状态 . 有没有办法避免内存泄漏,或者我真的担心内存泄漏,因为程序已经在那时退出 .

这也为我提出了另一个问题,这样的代码有害吗?

#include<stdio.h>
#include<cstdlib>
int main()
{
        char *p=(char *)malloc(sizeof(char)*1000);
        exit(0);
}

10 回答

  • 1
    #include<iostream>
    using namespace std;
    int main()
    {
        {
            std::string myname("Is there any leaks");
        }
        exit(0);
    }
    
  • 63

    如果您使用 exit() insist

    #include<iostream>
    int main(){
        {
            std::string myname("Are there any leaks?");
        }
        exit(0);
    }
    

    此外,当您从 main 返回时,返回的值将成为应用程序的退出代码 . 因此,如果要传递退出代码,请在 main() 中使用 return exitCode; 而不是 exit .

    关于那部分:

    这也为我提出了另一个问题,这样的代码有害吗?

    是的,因为它是一种编程习惯 .

    操作系统将清除您未能释放的任何内存,因此只要您没有设法占用所有系统内存和页面文件,就不应该损坏操作系统 .

    但是,编写草率/漏洞代码可能会变成习惯,因此依靠操作系统来清理混乱是一个坏主意 .

  • 5

    main 末尾使用 return 0; 而不是 exit(0); . exit 的使用规避了析构函数的执行 .

  • 0

    这也为我提出了另一个问题,这样的代码有害吗?的#include <stdio.h>中
    int main()
    {
    char * p =(char )malloc(sizeof(char) 1000);
    出口(0);
    }

    它对现代操作系统没有害处,因为它们会在流程结束时自动关闭流程所拥有的所有资源 .

    然而,它仍然是不好的做法,并且可能导致微妙且难以发现错误,经过几年的维护,代码慢慢变化,直到白天,这确实变得有害 . 我曾参与一些代码已有十年历史的项目,并且我已经学到了一些教训,其中一些相当苛刻 . 因此,即使目前没有出现问题,我也会避免编写这样的代码 .

  • 2

    在大多数情况下,由于已经给出了许多好的理由,因此值得自行清理:更好的可维护性,更好的检查工具实用性等等 .

    如果还有其他功能原因要清理,可能您的数据会保存到持久存储中,那么您别无选择 - 您必须清理(尽管您可能想重新考虑您的设计) .

    但是,在某些情况下,退出并“泄漏”可能会更好 .

    在程序结束时,您的流程将退出 . 当它这样做时,操作系统将恢复程序分配的任何内存,在某些情况下,它可以更快地执行此操作 .

    考虑一个大的链表,其中每个节点都是动态分配的,并带有一个实质上动态分配的结构 . 要清理它,您必须访问每个节点并释放每个有效负载(这反过来可能导致其他复杂结构被移动) .

    您最终可能会执行数百万次内存操作来运行此类结构 .

    用户想退出你的程序,他们坐在那里10秒,等待一堆垃圾处理发生 . 他们不可能对结果感兴趣 - 毕竟他们正在退出计划 .

    如果你让这个“泄漏”,操作系统可以更快地回收分配给你的进程的整个内存块 . 它不关心结构和任何对象清理 .

    http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx

    最终,您必须了解您的工具告诉您的内容,确保您正确使用它们 .

  • 65

    为避免内存泄漏,请从 main 返回状态,而不是调用 exit . 如果你返回零,你可以省略 return 语句,如果你愿意;在这种情况下,程序将退出状态为零 .

    这也为我提出了另一个问题,这样的代码有害吗?

    在现代操作系统上,它不会造成任何伤害 - 当程序终止时,所有资源都会自动回收 . 但是,它确实使用像Valgrind这样的工具更难找到真正的问题,所以如果可以的话,最好避免甚至无害的内存泄漏 .

  • 22

    在您的进程实际退出时,就像main()退出时一样,操作系统将回收分配给您的应用程序的所有资源 . 你如何退出并不是那么重要 - 至少在动态记忆方面如此 .

    如果你有一些分布式数据库连接打开或者什么,你应该使用atexit()处理程序来关闭它,并且直接退出强制终止可能会使它们无法运行而这将是坏事 - 但就你的操作系统资源而言,可能还好 .

    您还应该始终确保释放(手动)文件锁和类似的东西,因为它们可能不会因进程退出而消失 .

  • 4

    如果您想在不超过析构函数的情况下中断执行并传递返回代码,则抛出异常,并从 main() 中的异常中提取返回值 .

  • 0

    如果程序正在退出,则不必担心使用 mallocnew 分配的内存 . 操作系统会处理它 - 你的进程中的任何东西都使用共享内存或命名管道,它仍然是一个问题 .

  • 1

    添加不同的意见 .

    这样的代码并不是有害的 . 操作系统将在进程终止时关注所有内容 . 其他一切导致操作系统不稳定 . 只需确保您的持久数据(文件,...)一致 .

    为了更进一步和挑衅地说明,在程序退出时明确释放内存可能是有害的 .

    • 程序退出需要更长时间(在计算机关闭之前,您是否曾因等待程序退出而烦恼?)

    • 正确的破坏顺序并不总是微不足道的,特别是对于第三方组件(我记得有些程序可能在退出时崩溃)
      离开 main (*)后

    • The OS may not let you free memory并取消你的程序

    你冒这个风险只是为了让Valgrind给你一个特定的输出吗?(**)


    (*)

    #include<iostream>
    using namespace std;
    std::string myname("Is there any leaks");
    int main() {
            exit(0);
    }
    

    (**)当然,任何内存分析器的输出在没有“噪声”的情况下更有用 . 那么在调试模式下退出时只显式释放内存呢?

相关问题