0

I get this error when compiling and have checked out other questions here with no further progress:

funciones.c: In function ‘Lyapunov’: ../funciones.c:55:2: warning: function returns address of local variable [-Wreturn-local-addr]
return rgb;

First of all, I call the 'Lyapunov' function here in another .c : *Please note that in this '.c' I have only posted the part of the code where Lyapunov is called and also the declaration of rgb.

unsigned char rgb[3];

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

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

and the Lyapunov function from where I get the warning is here:

#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;
}

I assume there must be some kind of 'malloc' but my attempts trying to fix it have been a disaster. Thank you in advance. Any help is appreciated.

4
  • 2
    Duplicate hundreds of times over. Commented Feb 23, 2015 at 17:23
  • 2
    possible duplicate of warning C4172: returning address of local variable or temporary Commented Feb 23, 2015 at 17:24
  • You're trying to return rgb, which is a local array, and which will therefore be out of scope when you return. Commented Feb 23, 2015 at 17:24
  • 1
    Instead of returning an array pointer, I would pack 3 bytes of RGB into single int and return it, without messing with dynamic allocation. Commented Feb 23, 2015 at 17:25

4 Answers 4

2

You can use malloc as suggested, but looking at your code better idea would be to have a single static buffer passed to a function to have it's result (since you are using the buffer just once, and then discarding it's data), such that the function signature will be:

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

Then prior the use of the function you will need to define the buffer:

unsigned char rgb[3];

and then use it in your loop

Lyapunov(col,linea, rgb);

This way you will not need to worry about any memory leaks (resulting from the function).

Sign up to request clarification or add additional context in comments.

1 Comment

This one is definitely the most sensible. I don't know why I got so blind about the memory handling. Thank you.
2

to avoid all the messy malloc/free calls, etc. define the rgb in the caller and pass the address to the function.

Comments

1
unsigned char rgb[3];

is local to function and the scope of this array is within the function Lyapunov so once you exit the function this memory is no more valid. So the warning you are getting is the right one which says never return the local variables address which will lead to undefined behavior when used outside its scope.

Have your memory allocated of heap and then return the pointer as shown below.

unsigned char *rgb = malloc(3);

2 Comments

Since the function is used in loop, it would be a good idea to free it each iteration.
Using dynamic memory allocation is somewhat heavyweight and requires that the caller "knows" that the memory returned must be free'd. A better approach is for the caller to pass the required buffer to the function, and allocate/declare it as appropriate.
1

You trying to return an array rgb which stops existing outside of its local scope ( also the scope of the function ), which stops existing when you return from the function. Arrays cannot be returned by value.

You can put the array in a struct:

struct rgb_hold
{
    char rgb[3] ;
} ;

and return the struct, which can be returned by value.

4 Comments

always a bad idea to return other than fundamental data types and pointers
Code is not "returning an array rgb" - OP is only hoping to do that. unsigned char *Lyapunov() returns a pointer to a unsigned char. Yet returning a structure a valid approach. +1
@user3629249 : "Always" is a bit strong. To be done advisedly perhaps. In this case the size of the object returned is less that that of double for example.
In this case it may even make sense to use struct rgb { char r, char g, char b } ; (possibly with zero-packing if the file format requires three contiguous characters). It would certainly make the code clearer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.