2011-02-15 51 views
1

我有一个关于malloc行为的问题。 有2 C文件如果我们不能释放它,malloc的行为是什么

myTools.c和mainFile.c

mainFile.c是=>

int main(){ 
    int i=1; 
    char *request="blablabla"//vary in situation.Not static 
    while(i==1)//forever Loop 
    { 
     ... 
     strcpy(response,getFile(request)); 
     ... 
    } 
} 

myTools.c是==>

. 
.//something else 
. 
char *getFile(char *request) 
{ 
    char *retVal; 
    ...//some tcp request 
    retVal=malloc(strlen(buffer)); 
    strcpy(retVal,buffer); 
    ..//some char array operations 
    return retVal;  
} 
. 
.//something else 
. 

我不能找到了一种方法来释放retVal,或者我想知道我需要释放retVal?

它适用于m68k嵌入式平台上的uClinux,因此内存有限。

它可能会导致任何内存问题或任何内存不足?

或者影响程序的运行时行为?

回答

4

每次调用getFile()时都会泄漏内存。

一个解决办法是:

while(i==1)//forever Loop 
{ 
    ... 
    char* temp = getFile(request); 

    strcpy(response,temp); 

    free(temp); 
    ... 
} 
+0

响应得到它的内存? – 2011-02-15 13:31:29

+2

我们不知道 - 没有提供那部分源代码。我认为它被照顾到别的地方。 – Nick 2011-02-15 13:34:08

+0

但是,如果响应已经指向有效的内存,它应该只是传递给getFile()并且什么都不应该mableced – 2011-02-15 13:37:03

2

既然你回来从getFile()一个指针,也许你可以简单地把它分配给指针变量在main(),绕过双用strcpy()?然后你可以在main()内存free()

我不确定,但不明白为什么不行。

1

strcpy(response,getFile(request))可能会导致程序崩溃,因为response指向只读内存。

1
strcpy(response,getFile(request)); 

应splited到:

char *tmp = getFile(request); 
strcpy(response, tmp); 
free(tmp); 

这有时refered作为不被推荐的strdup()样式的分配。 您应该分配的缓冲区像调用代码:

char *buf2 = malloc(strlen(buffer)); 

,并呼吁

getFile(buf2, strlen(buffer), input); 
// use buf2 
free(buf2); 
1

在嵌入式系统中的malloc()经常被用来在启动时分配内存将用于在系统运行并从不免费()d。

但是你不应该定期做这样的事情,因为如果你不再释放()它会消耗你的记忆。

你在你的例子中正在做的是在while循环中每一轮泄漏一个值得记忆的内存。

你应该做的是在你的循环中调用free(),但是要注意这仍然可以在长时间运行的嵌入式系统中对内存进行分段。

如果事先你将需要多少内存事先知道:外循环一次的malloc缓冲区并在循环重复使用它:

response = malloc(MAX_BUF_SIZE); 
while (1) { 
    get_file(response, MAX_BUF_SIZE); /* always good to pass the buf size and check */  ... use response ... 
} 

或者,如果你不事先知道大小一个模式可以是:

response = NULL; 
size = 0; 
while (1) { 
    get_file(&response, &size); 
    ... use response ... 
} 

void get_file(char **buf, int *s) 
{ 
    size = ... somehow determine the needed size ... 
    if (size > *s) 
     *buf = realloc(*buf, size);  /* only does free/malloc internaly if it has to no room */ 
    strncpy(*buf, whatver, size); 
} 

你应该总是使用strncpy永不strcpy请!

在您的示例中使用strcpy令人困惑,它无法看到响应获取其内存,它是静态分配?它之前是否已经配对?

如果响应已经指向vaid缓冲区,您应该将指针指向缓冲区并传递到getFile()并直接将buffer复制到那里。

如果响应没有指向有效的内存缓冲区,则无论如何这都不起作用。

0

是的,它最终会导致内存不足,这将导致程序崩溃。

有助于解决此类问题的一条简单规则是始终记住将 中的内存释放到与分配位置相同的范围(如果可能的话)。

在你的情况下,显然不可能在调用返回之后释放它,因此在父范围内实际分配它是有意义的。在main函数中,将分配的指针作为第二个参数传递给getFile函数,并直接写入它,假设您确保它足够大以包含所有字符。

0

首先,* retVal的被放置在 的GetFile功能,因而 范围* retVal的仅限于该特定功能,它使用 将自动设定的内存空间,以释放功能终止一次 /回报。

变量的范围决定了它的生命周期/可用性,一旦生命周期结束,并且你不释放数据块保留在那里,它可以通过指针访问,但是内存块是一种标记为免费,之后被覆盖,没有任何问题。

其次,尼克是非常正确的,你 会在每次的GetFile时间() 叫浪费内存,因为它是在主要功能 并具有范围,直至程序运行。

希望这会有所帮助,如果没有,我会很乐意帮助只是让我知道:)

1

每当你创造一些功能,你需要考虑资源管理的界面 - 各种物体的寿命以及这些物体的寿命如何管理。对于没有实现垃圾收集的C和C++语言尤其如此,但即使在垃圾收集语言中,也需要考虑这一点(对于非内存资源并且可能确保不保存对象引用无限期)。

无论如何,对于C来说,API可以通过多种方式处理'输出'对象。一些更常见的模式是:

  1. 具有呼叫者提供缓冲或对象位置的结果在
  2. 具有被叫方分配缓冲区或对象,并返回一个指向所分配的对象
  3. 有调用者直接从函数返回对象 - 这仅适用于具有固定大小(内部类型或结构)的项目 - 它不适用于任意字符串。所以我不会进一步讨论。

对于选项1,调用者通过传递指针提供缓冲区来放置结果。对于可变长度数据,如字符串,重要的是该接口还允许调用者传递输出缓冲区的大小,以避免写入缓冲区之外。为了您的getFile()功能,其原型可能看起来像:

int getFile(char const* request, char* result, int result_size); 

的调用者传递一个指针放置结果,并在缓冲区中传递的大小。该功能可能会在失败时返回一个负数(比如网络故障)以及成功时的结果大小。如果成功返回的大小大于提供的缓冲区大小,则调用者知道全部结果未放置在缓冲区中(因为它不够大)。如果你走这条路线,考虑'\ 0'终结符字符很重要,并且清楚地指出它是否包含在返回值中,以及如果结果太大(我推荐),是否终止缓冲区。另外,请确保如果传入一个零大小的缓冲区,函数不会向缓冲区写入任何内容,而不管是否传入非NULL指针(这是一种常见模式,可让函数返回所需的大小在这种情况下的缓冲区)。

对于选项2,该函数将分配一个适当的缓冲区并返回一个指向调用者的指针。在这种情况下,调用者需要有一种方式来释放缓冲区,以避免内存泄漏。一种方法是记录调用者需要调用函数返回的指针free()(意味着函数将使用malloc()calloc()分配指针)。另一个是使用函数的接口还包括一个解除分配例程,也许getFile_free()(如果我要走这条路线,我肯定会重新考虑这些函数的命名)。这给了这个API的实现自由分配它返回的缓冲区,但它看起来合适 - 它不限制使用malloc()/free()(尽管它可以)。

对于嵌入式系统(尤其是小型的 - 也许不是基于Linux的系统),我认为人们可能会选择选项1.这使得API的用户可以自由地完全避免动态内存分配,并且它很常见为嵌入式系统不使用动态内存。此外,使用动态内存分配的系统仍然可以使用选项1的模式 - 它只需要多一点工作,但是该工作可以用与选项2完全相同的东西包装,因此您可以拥有自己的蛋糕并吃掉它。

相关问题