C程序异常终止导致的潜在内存泄漏

C程序异常终止导致的潜在内存泄漏,c,memory-leaks,malloc,free,C,Memory Leaks,Malloc,Free,Windows和Linux 当我在C程序中分配内存时,良好的编码要求我在程序结束前释放内存 假设如下: int main (int argc, char *argv[]) { char *f_name; FILE *i_file; f_name = malloc(some_amount); // put something in f_name */ i_file = fopen(f_name, "r"); if (i_file == NULL)

Windows和Linux

当我在C程序中分配内存时,良好的编码要求我在程序结束前释放内存

假设如下:

int main (int argc, char *argv[]) {
    char *f_name;
    FILE *i_file;

    f_name = malloc(some_amount);
    // put something in f_name */
    i_file = fopen(f_name, "r");
    if (i_file == NULL) {
        perror("Error opening file.");
        exit(EXIT_FAILURE);
    }
    free(f_name);
    return EXIT_SUCCESS;
}
如果程序在我调用“free”之前终止,那么当程序退出时,操作系统会恢复任何未释放的内存吗?或者,在系统重新启动之前,我会从3Gb左右的可用内存中一点点地消耗掉吗


谢谢,马克。

在Windows和Linux等流行操作系统上,你不必担心这个问题

当进程终止时,虚拟内存不再存在。因此,在进程终止后,它不可能泄漏

无论进程是否仍在运行,物理内存始终属于操作系统,可以随意分配。(除非您锁定分配,否则在这种情况下,当相应的虚拟内存映射被破坏时(无论如何,在进程终止时发生),分配将停止锁定。)

有一些资源没有被清理(比如某些类型的共享内存),但这是非常奇怪的

调用
malloc
时,通常只保留后备存储(基本上是RAM+swap),并创建虚拟内存映射(基本上是空闲的)。当您第一次写入该虚拟内存映射时,内存的物理页(RAM)被映射到其中以“备份”它。RAM总是属于操作系统,可以随意使用,如果操作系统认为明智的话,它会将RAM重新用于其他目的

当进程终止时,它的地址空间就不存在了。这意味着任何虚拟内存映射或保留都会消失。当虚拟内存映射消失时,非共享物理页的使用计数将降至零,从而使这些物理内存页变为空闲


这是值得详细了解的,因为如果你不了解引擎盖下发生的事情,你很容易得出关于边缘情况的错误结论。此外,这将为您提供一个框架,将文件映射、内存过度使用和共享内存等概念插入其中。

内存由操作系统回收


有些程序(如Web服务器)永远不会退出,它们只是继续运行并为请求提供服务。它们在技术上分配的内存不需要返回。

实际上,当进程终止时,程序的内存分配会自动释放。但是,如果函数调用在该函数的代码块内的
free()
delete
调用之前收到异常,则不会释放内存,除非它被某种智能指针或对象引用。自动释放分配内存的一个建议选项是使用
std::shared_ptr
,如下所示:

void BadFunction(){
    char *someMemory = (char *)malloc(1024);
    DoSomethingThatMakesAnException();
    delete someMemory;// This never gets called!
}

void GoodFunction(){
    std::shared_ptr<char> someMemory = std::shared_ptr<char>((char *)malloc(1024));
    DoSomethingThatMakesAnException();
    // someMemory is freed automatically, even on exception!
}
void BadFunction(){
char*someMemory=(char*)malloc(1024);
doSomethingthatsanException();
delete someMemory;//这永远不会被调用!
}
void GoodFunction(){
std::shared_ptr someMemory=std::shared_ptr((char*)malloc(1024));
doSomethingthatsanException();
//someMemory会自动释放,即使是在异常情况下!
}

在您的示例中,使用此分支确实会导致内存泄漏:

f_name = malloc(some_amount);
// put something in f_name */
i_file = fopen(f_name, "r");
if (i_file == NULL) {
    perror("Error opening file.");
    exit(EXIT_FAILURE);            // <--- f_name leaks here!
}
f_name=malloc(部分金额);
//用f_的名字写东西*/
i_file=fopen(f_名称,“r”);
如果(i_文件==NULL){
perror(“打开文件时出错”);

exit(exit_FAILURE);//是的,进程终止,一切正常。一个好的程序不会意外终止。只有在调用未定义的行为时才会发生这种情况。(一个好的程序也不需要被终止)。请参阅我对silentboy答案的评论。这种答案可能会非常混乱,并导致误解。你知道什么“记忆"意思是?物理内存?备份内存?虚拟内存?说得对,但我认为他指的是
malloc
ed内存,因为他的示例中包含了它。但实际上不清楚这意味着什么,因为在那些平台上,
malloc
只保留地址空间和备份存储。有人不会问这种问题如果他们已经理解了虚拟地址空间是什么,并且当进程终止时,虚拟地址空间就不再存在。你……你会意识到这是一个C标记问题……对吗?你应该:1…2…3。选择一种语言:C或C++……在这个问题中,C被标记,但是在你的答案中,(无效)。鼓励C++。幸运的是,C没有例外,所以这个场景是不相关的。@ SEB——你是说C和C++的混合是“无效”C++?这是一个风格断言,而不是函数。我所提供的代码将很好地工作,不管你喜欢与否。虽然我在代码中假设C++支持,但因为它不符合编程风格,所以调用它无效,这就像是说使用Windows是“无效的”,因为您更喜欢Linux。因为你不理解它的定义,让我们从这一点开始,因为C和C++都是由法律文件定义的,所以我们可以使用这个定义:“(尤其是官方文件或程序),因为它违反了法规或法律而没有被法律承认。”.在你试图争论这两种语言之前,你应该按照标准学习这两种语言。