The discussion revolves around a C function that returns a pointer to a local array, leading to compiler warnings about returning the address of a local variable. The original poster is modifying global variables and returning results in array literals, which is flagged as problematic since the memory for these literals is freed once the function exits. The community advises against using global variables and suggests alternatives such as allocating memory outside the function or returning a structure containing the results. The use of assertions to ensure unique input arrays is discussed, with some questioning their necessity if the programmer believes the inputs are correctly managed. The conversation also touches on memory management practices, highlighting the importance of manual memory allocation to avoid potential memory leaks. Overall, the consensus emphasizes safe coding practices to prevent future issues, especially in C programming.
Yes I've already looked on SO! None of the answers contain the word "may". My story is that I am passing in references to global variables, modifying them, and returning them in array literals. I suppose it must complaining about the array literals (c99) rather than the variables themselves, but how should I re-write it ([EDIT] the code runs and gives the correct answer BTW)?
Here is the function:
double *t_sin_cos (double *S, double *C, double *U, int k) {
    assert((S != C) && (S != U) && (C != U));
    assert(k >= 0);
    if (k == 0) {
        sincos(U[0], S, C);
        return (double[2]) {S[0] / k, - C[0] / k};
    } else {
        S[k] = 0.0;
        C[k] = 0.0;
        for (int j = 0; j < k; j++) {
            S[k] += (k - j) * U[k - j] * C[j];
            C[k] += (k - j) * U[k - j] * S[j];
        return (double[2]) {S[k] / k, - C[k] / k};
and here is the error message:
taylor-ode.c: In function ‘t_sin_cos’:
cc1: warning: function may return address of local variable [-Wreturn-local-addr]
taylor-ode.c:70:28: note: declared here
         return (double[2]) {S[0] / k, - C[0] / k};
cc1: warning: function may return address of local variable [-Wreturn-local-addr]
taylor-ode.c:78:28: note: declared here
         return (double[2]) {S[k] / k, - C[k] / k};
									
  • Research team improves fuel cell durability with fatigue-resistant membranes
  • Self-extinguishing batteries could reduce the risk of deadly and costly battery fires
  • Chemists decipher reaction process that could improve lithium-sulfur batteries
  • You could create copies of the variables and return that. The warning is that you may be returning an address on the stack that will only be valid as long as you don't call more functions which call functions... and obliterate the area containing the local variable.
    It's only a warning and your code works but the danger here is that some future modification may cause it not to work and so you should heed it. If I got this warning I would definitely heed it because debugging a C/C++ program for a runtime stack based error is no fun.
    typedef struct { double x, y; } pair;
    pair t_sin_cos (double *S, double *C, double *U, int k) {
        /* code */
            return (pair) {S[k] / k, - C[k] / k};
    This actually returns a copy of the structure so it's safe.
    		
    typedef struct { double x, y; } pair;
    pair t_sin_cos (double *S, double *C, double *U, int k) {
        /* code */
            return (pair) {S[k] / k, - C[k] / k};
    This actually returns a copy of the structure so it's safe.
    I like your option 2, as it seems more in the spirit of my attempt.  As I currently understand it my mistake was not to declare the array outside the function.  So if I have to do that then a struct would be much nicer anyway.  Thanks for the tip!
    Returns a pointer to an array that didn't exist when the function was called.  The compiler is correct to complain.  When the function terminates, that space is freed, and the pointer points at some free space that at one time held the correct answer.
    Also, does the asset mean the input arrays don't overlap or that they don't have the same first element. Returns a pointer to an array that didn't exist when the function was called. The compiler is correct to complain. When the function terminates, that space is freed, and the pointer points at some free space that at one time held the correct answer.
    Also, does the asset mean the input arrays don't overlap or that they don't have the same first element. I'm still working on the first part, it's not urgent as I already have working arbitrary precision code. I just wanted to play a bit doing a double version with functions returning values (the existing code uses pointer parameters). Also I have probably been influenced by my Python version which returns tuple values in some cases, but the fine details are of course hidden ;)
    As to your second question, the asserts are just to make sure that all the appropriate parameters are unique (I re-use a few temporary variables), I have not considered overlapping as I believe all arrays are dimensioned and allocated correctly (I don't manipulate addresses myself), and nothing is copied or changes size. Is that a good enough argument? Well, if you are arguing you don't need to test more than you do because you know you set them up right, why do the assert (or...um... "asset"...oops) at all? OK guys steady on, I am not going to return the address of a local variable, really. I'm either going to fix the code as per #5 or abandon it as the MPFR version is the one I use and it doesn't do that anywhere. BTW I'm not a software dev or intending to be one, and I'm not trying to sell anything. The problem domain is far more interesting to me than the implementation to be honest. These programs are simple tiny things, however I have worked as a software tester so do I understand what you are saying really ;)
    Oh, the asserts are just there as additional (on top of the compiler) tripwires in case I make a refactoring boo-boo, they are not meant to be exhaustive.
    Having said that, thanks for all your help, my question is well and truly answered, hope it is useful to others learning c!
    OK I think this is pertinent to the OP.
    I have since looked into a function that I wrote to create arrays of MPFR variables. It uses malloc() and returns the address of that memory, and yet it works without raising errors. Apparently this does not count as a local variable for the purposes of the error message!
    My mistake was to refactor something like this to return either an array or struct defined within the function. Apparently this does count as a local variable for the purposes of the error message.
    My conclusion? Always use manual memory allocation for factory functions. Is that reasonable?