【问题标题】:warning: function returns address of local variable [-Wreturn-local-addr]警告:函数返回局部变量的地址 [-Wreturn-local-addr]
【发布时间】:2015-04-25 02:49:14
【问题描述】:

我在编译时收到此错误,并在此处检查了其他问题,但没有进一步的进展:

funciones.c:在函数“Lyapunov”中:../funciones.c:55:2:警告: 函数返回局部变量的地址 [-Wreturn-local-addr]
返回 rgb;

首先,我在另一个 .c 中调用“Lyapunov”函数: *请注意,在这个“.c”中,我只发布了调用 Lyapunov 的代码部分以及 rgb 的声明。

unsigned char rgb[3];

while((int)linea>inicial){                  
        for(col=0;col<asize;col++){             
               rgb = Lyapunov(col,linea);

               fwrite(rgb, 3, image);
        }
        linea++;
}

我得到警告的 Lyapunov 函数在这里:

#include "lyapunov.h"
#include <math.h>


#define CLAMP(x) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x))


unsigned char *Lyapunov(int ai, int bi){
    int n, m;
    double a, b, lambda, sum_log_deriv, prod_deriv, r, x, rgb_f[3];
    unsigned char rgb[3];   


    double lambda_min = -2.55;
    double lambda_max = 0.3959;

    a = amin + (amax-amin)/asize*(ai+0.5);
    b = bmin + (bmax-bmin)/bsize*(bi+0.5);
    x = 0.5;


        for (m = 0; m < seq_length; m++) {
            r = seq[m] ? b : a;
            x = r*x*(1-x);
        }

    sum_log_deriv = 0;
    for (n = 0; n < nmax; n++) {
        prod_deriv = 1;
        for (m = 0; m < seq_length; m++) {
                r = seq[m] ? b : a;

                prod_deriv *= r*(1-2*x); 
                x = r*x*(1-x);
        }
        sum_log_deriv += log(fabs(prod_deriv));
    }
    lambda = sum_log_deriv / (nmax*seq_length);

    if (lambda > 0) {
        rgb_f[2] = lambda/lambda_max;
        rgb_f[0] = rgb_f[1] = 0;
    } else {
        rgb_f[0] = 1 - pow(lambda/lambda_min, 2/3.0);
        rgb_f[1] = 1 - pow(lambda/lambda_min, 1/3.0);
        rgb_f[2] = 0;
    }


    rgb[0] = CLAMP(rgb_f[0]*255);
    rgb[1] = CLAMP(rgb_f[1]*255);
    rgb[2] = CLAMP(rgb_f[2]*255);

    return rgb;
}

我认为一定有某种“malloc”,但我试图修复它的尝试是一场灾难。 先感谢您。任何帮助表示赞赏。

【问题讨论】:

  • 重复数百次。
  • 您正在尝试返回 rgb,这是一个本地数组,因此在您返回时将超出范围。
  • 我不会返回数组指针,而是将 3 个字节的 RGB 打包到单个 int 中并返回它,而不会影响动态分配。

标签: c


【解决方案1】:

您可以按照建议使用 malloc,但查看您的代码更好的想法是将单个静态缓冲区传递给函数以获得结果(因为您只使用了一次缓冲区,然后丢弃它的数据),这样函数签名将是:

void Lyapunov(int ai, int bi, unsigned char rgb[]);

那么在使用函数之前你需要定义缓冲区:

unsigned char rgb[3];

然后在你的循环中使用它

Lyapunov(col,linea, rgb);

这样您就不必担心任何内存泄漏(由函数引起)。

【讨论】:

  • 这个绝对是最理智的。我不知道为什么我对内存处理如此盲目。谢谢。
【解决方案2】:
unsigned char rgb[3];

是函数本地的,并且这个数组的范围在函数Lyapunov 内,所以一旦你退出函数,这个内存就不再有效。所以你得到的警告是正确的,它说永远不要返回局部变量地址,这将导致在其范围之外使用时未定义的行为。

将你的内存分配给堆,然后返回指针,如下所示。

unsigned char *rgb = malloc(3);

【讨论】:

  • 由于函数是循环使用的,所以每次迭代都释放它是个好主意。
  • 使用动态内存分配有点重量级,并且要求调用者“知道”返回的内存必须是空闲的。更好的方法是调用者将所需的缓冲区传递给函数,并根据需要分配/声明它。
【解决方案3】:

为了避免所有乱七八糟的 malloc/free 调用等,在调用者中定义 rgb 并将地址传递给函数。

【讨论】:

    【解决方案4】:

    您试图返回一个数组rgb,该数组在其本地范围(也是函数的范围)之外停止存在,当您从函数返回时该数组停止存在。数组不能按值返回。

    你可以把数组放在一个结构体中:

    struct rgb_hold
    {
        char rgb[3] ;
    } ;
    

    并返回struct,可以按值返回。

    【讨论】:

    • 除了基本数据类型和指针之外,返回总是一个坏主意
    • 代码不是“返回数组rgb”——OP 只是希望这样做。 unsigned char *Lyapunov() 返回指向 unsigned char 的指针。然而,返回一个结构是一种有效的方法。 +1
    • @user3629249 :“总是”有点强。也许要明智地完成。在这种情况下,返回的对象的大小小于double 的大小。
    • 在这种情况下,使用struct rgb { char r, char g, char b } ; 甚至可能有意义(如果文件格式需要三个连续字符,则可能使用零包装)。它肯定会使代码更清晰。
    猜你喜欢
    • 2016-08-15
    • 2021-12-12
    • 2015-05-06
    • 2016-12-05
    • 2011-10-17
    • 1970-01-01
    • 2013-01-30
    相关资源
    最近更新 更多