2016-09-25 103 views
0

我想了解从函数调用返回指针的行为。假设我有以下简单的代码:在返回语句之前了解空闲()缓冲区

int main(){ 
    int i; 
    float *ssd; 
    ssd = test(); 

    for (i = 0; i < 3; ++i) { 
     printf("%f, ", ssd[i]); 
    } 
    printf("\n \n"); 

    memset(ssd, 0.0, 3*sizeof(float)); 

    for (i = 0; i < 3; ++i) { 
     printf("%f, ", ssd[i]); 
    } 
    printf("\n \n"); 

} 

float *test(){ 

    float *buff = malloc(3* sizeof(float)); 
    int i; 
    for (i = 0; i < 3; ++i) { 
     buff[i] = (float) (6.31 + i); 
    } 

    free(buff); 
    return buff; 

} 

正如你看到的,我创建了一个临时缓冲区内bufftest()。在我回来之前,我在return声明之前释放了buff。尽管我测试了它并且结果如预期,但我不明白test()函数如何返回buff值,即使free(buff)return之前buff?

+0

相关:http://stackoverflow.com/q/6441218/509868 – anatolyg

+2

没有与不确定的行为一个C程序是不可能的。 – PSkocik

+2

这是不正确的代码。它会导致腐败。这似乎是免费的错误后使用 –

回答

5

free(buff); 

任何进一步的操作,其提领buff未定义行为

你的功能test()分配一个缓冲区,但随后free其返回到main,为ssd之前这样。

因此,当ssdmain中被取消引用时,虽然指针仍然具有相同的值,但它已被分配malloc,它不再指向您拥有的存储器。所以从那时起,任何事情都可能发生。您的代码可能仍然有效,或者可能不会。

+0

谢谢你的解释。在这种情况下,请介绍一下解释这种情况以避免模糊不清的最佳方法吗?在'return'语句之后放置'free()'将无法正常工作,所以我不知道下一步该怎么做! – Adam

+0

在完成使用其内容后,您只能“释放”内存。只要'main'中'ssd'的值没有改变,当你没有进一步的使用时,你可以在'main'中'free(ssd)',因为它仍然有和'buff'相同的指针值= malloc(3 * sizeof(float))'在函数中。 –

+0

@亚当如果你想知道“如何修正你的代码”,而不是“什么是错的”,请问一个单独的问题。您可能想要返回一个数组(使用[此处](http://stackoverflow.com/q/11656532/509868)或[这里](http://stackoverflow.com/q/8617889/509868)中描述的技术)你的函数,而不是使用'malloc'和'free'。 – anatolyg

0

最初由buff指向的内存不会被覆盖,因此会保留您存储在其中的值。

这通常是我们所说的“包含垃圾的内存”,但是自从初始化它然后一切正常。

0

从libc中的文档,

偶尔,免费其实可以返回内存操作系统 ,使过程更小。通常,它所能做的只是允许稍后调用malloc以重新使用空间 。与此同时,程序中的空间仍然是 ,作为malloc内部使用的自由列表的一部分。

免费电话并不能保证空间被清理。但是,什么是保证(至少由GNU libc实现)是

  1. 从而释放将可能使用的任何动态内存分配例程的将来调用运行空间。

为了证明这一点,我修改了你的程序如下。它基本上在你的test()函数中添加了一个for循环,该函数刚分配n次并释放该buff(e.x.10次),并打印缓冲区的内容。所以每次运行程序时,它都会首次打印内容,当malloc()和free()被调用时,* buff的内容被清除并且垃圾被打印。 (在Mac上测试,gcc 4.8+)。 希望这有助于。

#include<stdlib.h> 
 
#include<stdio.h> 
 
#include<string.h> 
 
float *test(){ 
 
    float *buff = malloc(3* sizeof(float)); 
 
    int i, j; 
 
    for (i = 0; i < 3; ++i) { 
 
    buff[i] = (float) (6.31 + i); 
 
    } 
 
    free(buff); 
 
    int n = 10; 
 
    for(i=0;i<n;i++) 
 
    { 
 
    printf("Iteration %d ", i); 
 
    for (j = 0; j < 3; ++j) { 
 
     printf("%f, ", buff[i]); 
 
    }  
 
    printf("\n"); 
 
    buff = malloc(3 * sizeof(float)); 
 
    free(buff); 
 
    } 
 
    return buff; 
 

 
} 
 
int main(){ 
 
    int i; 
 
    float *ssd; 
 
    ssd = test(); 
 
    printf("\n \n"); 
 
    memset(ssd, 0.0, 3*sizeof(float)); 
 
    for (i = 0; i < 3; ++i) { 
 
    printf("%f, ", ssd[i]); 
 
    } 
 
    printf("\n \n"); 
 
}