calloc可以安全地使用吗?

时间:2016-08-14 11:53:35

标签: c

我是一名几乎没有C / C ++经验的Java程序员,他试图调整一些与JNI一起使用的简单C / C ++代码。

我读到用单个calloc()分配的数组(或任何其他内存块)应始终使用malloc返回的SAME指针进行单个free()调用来释放。如果它不是免费的,它会导致内存泄漏。

我适应的C / C ++代码使用calloc(),但没有相应的free()调用。是否有任何情况下它不应该有一个free()调用,或者代码写得不好?

4 个答案:

答案 0 :(得分:3)

calloc(...)malloc(...)应始终附带相应的free(),以便应用程序/操作系统可以回收内存以用于其他目的。不释放内存的应用程序将“泄漏”该内存并使其无法使用。

如果您不使用free(),合理的操作系统将在应用程序关闭时再次使该内存可用,但依赖于操作系统来清理任何内存泄漏的程序编程错误,应该修复

这(正如您所知)与Java不同,它有一个垃圾收集器,可以定期清理任何不再使用的内存。

作为一般性补充说明,不需要使用相同指针来释放内存。例如,您可以这样做:

// Create an array of 10 integers.
int *x;
x = calloc(10, sizeof(int));

// Create another pointer 'y', which uses the same array as x.
int *y;
y = x;

// Delete the array. Both 'x' and 'y' are unusable now.
free(y);

答案 1 :(得分:2)

分配应始终与库代码中的解除分配和循环运行的代码配对。

基本上,您不希望不同的未引用内存累积,从而增加您的进程的内存消耗。

当你只想退出时跳过解除分配是允许的(虽然通常不赞成),如果你有很多很多的解除分配,它可以加快你的退出。

在C ++中,分配和解除分配可以通过析构函数(RAII)隐式配对:

#include <utility>
#include <memory>
#include <stdio.h>
#include <stdlib.h>

struct Free{
    void operator() (void* x){ 
        free(x); 
    }
};

int main(){
    char *p = new char; 
    delete p; //an explicit deallocation

    std::unique_ptr<char, Free>  ptr { (char*)calloc(1,100) };
    return 0;
    //an implicit deallocation
    //-- you don't see the free but unique_ptr's destructor does call it here
}

事实上,依赖于析构函数是在C ++中处理动态内存的首选方法。

您可以使用valgrind之类的工具来检查程序运行中的分配和解除分配是否配对(当您第一次直接或间接调用new时,g ++标准库通常会进行一次不配对的分配,但其余的您的分配应与free s)匹配

如果我通过以下方式运行上述程序:

valgrind ./a.out

我明白了:

==25629== Memcheck, a memory error detector
==25629== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25629== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==25629== Command: ./a.out
==25629== 
==25629== 
==25629== HEAP SUMMARY:
==25629==     in use at exit: 72,704 bytes in 1 blocks
==25629==   total heap usage: 3 allocs, 2 frees, 72,805 bytes allocated
==25629== 
==25629== LEAK SUMMARY:
==25629==    definitely lost: 0 bytes in 0 blocks
==25629==    indirectly lost: 0 bytes in 0 blocks
==25629==      possibly lost: 0 bytes in 0 blocks
==25629==    still reachable: 72,704 bytes in 1 blocks
==25629==         suppressed: 0 bytes in 0 blocks
==25629== Rerun with --leak-check=full to see details of leaked memory
==25629== 
==25629== For counts of detected and suppressed errors, rerun with: -v
==25629== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

这意味着一切都很好,因为只有标准库(72,704字节的那个)所做的分配在解除分配时仍未配对。

答案 2 :(得分:1)

这些天操作系统在程序退出时释放程序分配的内存。但依靠操作系统为您释放内存是一种不好的做法。所以很明显它的写得很糟糕。

答案 3 :(得分:1)

操作系统在进程退出时释放所有进程资源,但如果你的程序有一个主循环并且频繁分配内存,那么依靠它就不是一个好主意;)

相关问题