2013-10-12 94 views
1

我(尝试?)返回分配给函数内部的内存。在C函数中引用计数和在函数内部分配内存

假设我在这里写的东西没有明显的问题(并没有测试)内存是如何释放或不释放的?之后我需要free(bob),因为他不在堆上,对吧?

我在another accepted answer just now的C中读了一些关于引用计数的内容,但我真的不记得C有什么像垃圾回收器。

char* strCat5000(char *fmt, ...) 
{ 
    char buff[5000]; 
    char *ret_; 
    va_list arg_ptr; 
    va_start(arg_ptr, fmt); 
    vsnprintf(buff, sizeof(buff), fmt, arg_ptr); 
    va_end(arg_ptr); 
    //ret_ = malloc((char*)(strlen(buff)+1)*sizeof(char)); //Allocated inside function 
    ret_ = (char*)malloc((strlen(buff)+1)*sizeof(char)); //moved (char*) .. typo 
    ret_ = strcpy(ret_,buff); 
    return (ret_); 
} 
... 
void findBob() 
{ 
    char * bob; 
    bob = strCat1000("Server is %s for %d seconds.", "on fire", 35329); 
    printf("%s", bob); 
    free(bob); //bob needs to be freed here or he'll leak when findBob ends??? 
} 
+2

引用计数与垃圾回收没有关系。这是一种用于管理内存的模式,但它仍然是程序员的手动操作POV –

+0

你是对的,C没有垃圾收集器。你的代码有问题吗? – Barmar

+0

@EdS .:不一定。 Python使用引用计数,它对程序员是透明的。 – icktoofay

回答

1

是的。你必须在findBob()方法中“释放Bob”,否则在你的程序中没有关于该特定内存块的进一步概念=>你将有泄漏。所以,简而言之:是的,这个记忆必须被释放。

但是,只是一个方面说明:这种代码是非常“容易出错”。如果你有一个功能分配呼叫者应该释放的内存,那么有一个方法或类似的方法可能是一个好主意,这使得这个目的非常明显。调用malloc()free()调用在的相同抽象级别上通常是个好主意。例如。在这种情况下,同一个.c文件中的两个函数可能是一个合理的“抽象级别”。

+0

我完全不同意这样的观点,即释放第三个函数内部以保留*抽象级别*使得代码更具可读性或可维护性,但是...从围绕interwebs狩猎,这看起来确实是合适的。 – AppFzx

+0

那么,如果你想到一个公共API(这可能会也可能不是),有一个返回某种形式的数据结构的'get_foo()'方法和一个'free_foo()'方法耦合起来感觉更自然并伴随它来处理重新分配。是的,它可能像“无意义的额外代码”,但我认为它很好。例如,如果'get_foo'会分配一个对象,该对象具有一个必须被释放的嵌入式额外对象,例如?所以,我其实认为这种方法很好,它使得代码在我眼中更加健壮。 –

1

你是对的,如果你从一个函数返回堆分配的数据,它最终需要被释放(除非你需要它直到程序完成,那么你可以依赖于所有内存在释放时该过程退出)。

引用计数是一种用于避免过早释放内存的技术。如果您可以将一个指针复制到多个变量中,那么当它们中的任何一个仍在使用它时,您都不想释放它。您分配一个包含refcount成员的结构。每次将指针指定给另一个变量时,都必须增加refcount,并减少之前变量指向的refcount。当引用计数下降到0时,您可以拨打free()

Wikipedia

+0

“,那么你可以依赖于当进程退出时所有内存都被释放的事实。没错,但是这种编码通常被认为有点草率,我会说...... –

+0

这部分内容:“你可能依赖于当进程退出时所有内存都被释放的事实”让​​我感到毛骨悚然。是否在维基百科以外的地方记录了与所有(有信誉的)编译器一起工作的跨平台? – AppFzx

+0

@AppFzx:我不认为在这不适用的生产环境中会有操作系统。尽管如此,我同意100%,编写这样的代码是不好的做法。当程序退出时运行断言以确保所有(全局)状态已被正确释放,或者类似的东西(当然也执行该释放操作),这会更好一些。 –

1

要解决上述问题,您有两种方法。

1st是你在做什么,那就是free bob在使用后。因为没有什么是automatic在c。

第二是你可以通过parameterstrCat1000其中你想存储结果(比如说它是store_var)。在这种情况下,store_var将在堆栈中(它必须在findBob内部声明),并且在findBob结束后它将自动解除分配。

如果你想从free免费获得免费的malloc

像这样的东西可以工作:

void findBob() 
{ 
    char store_var[1000]; 
    strCat1000(store_var,"Server is %s for %d seconds.", "on fire", 35329); 
    ... 

void strCat1000(char to_save[],char *fmt, ...) 
{ 
    ret_ = strcpy(to_save,buff); //check for lengths also. 
    ... 
0

要使它真正简单,我写的代码(C++)以下的和平。只需运行它并使用任务管理器监视您的代码内存使用情况。

#include "stdafx.h" 
#include<iostream> 
#include <conio.h> 

using namespace std; 
int * allocate(unsigned size) 
{ 
    int * arr = new int[size]; 
    for(unsigned i=0;i<size;i++) 
     arr[i] = i; 
    return arr; 
} 
int main() 
{ 
    int * p; 

    p = allocate(1000000); 
    getch(); // Here you still occupy the memory 
    free(p); // here you free the memory you occupy in the function 
    getch(); // here you should see that memory is freed before returning from the main 
    return 0; 
} 
+0

这看起来很合理,但我对这个项目的任意限制只是C,因为我决定让C++的许多问题让我感到不满。事实上,只要我有时间喘口气,我就会转移到http://software.intel.com/en-us/intel-cilk-plus。 – AppFzx