Using a C string gives a warning: "Address of stack memory associated with local variable returned"
Asked Answered
V

4

64

I am not a C programmer, so I am not that familiar with C-string, but now I have to use a C library, so here is a shortened version of my code to demonstrate my problem:

char** ReadLineImpl::my_completion () {
    char* matches[1];
    matches[0] = "add";

    return matches;
}

I am getting this warning:

Warning - address of stack memory associated with local variable 'matches' returned

And my program does not seem to work properly (might be because of the above mentioned warning).

What does the warning imply? And will it cause any problems?

Volute answered 4/8, 2013 at 8:23 Comment(2)
You're returning the address to the first character pointer which is allocated on stack and which ceases to exist after you exit the function.Jedthus
Possible duplicate: C++ Returning reference to local variableRutledge
M
83

Variable char* matches[1]; is declared on the stack, and it will be automatically released when the current block goes out of scope.

This means when you return matches, memory reserved for matches will be freed, and your pointer will point to something that you don't want to.

You can solve this in many ways, and some of them are:

  1. Declare matches[1] as static: static char* matches[1]; - this will allocate space for matches in the static space and not on the stack (this may bite you if you use it inappropriately, as all instances of the my_completion function will share the same matches variable).

  2. Allocate space in the caller function, and pass it to the my_completion function: my_completion(matches):

    char* matches[1];
    matches = my_completion(matches);
    
    // ...
    
    char** ReadLineImpl::my_completion (char** matches) {
         matches[0] = "add";
    
         return matches;
    }
    
  3. Allocate space in the called function on the heap (using malloc, calloc, and friends) and pass the ownership to the caller function, which will have to deallocate this space when not needed any more (using free).

Monocot answered 4/8, 2013 at 8:27 Comment(5)
Thanks I got it. The worst thing is that this is the second time that get this kind of problem:) anyways, thank you very muchVolute
Assuming that it's the GNU readline, this will cause a crash, since readline will free the memory returned by the completion function.Cari
@MatsPetersson This does seems like readline - and in that case you are right. I will upvote your answer!Monocot
declaring matches as static will allocate space on static space, not on heap.Perfume
Third option is allocate memory in heap by calling callocBlondell
C
14

When you return the matches array, you are returning the address of the first element. This is stored on the stack inside my_completion.

Once you return from my_completion that memory is reclaimed and will (most likely) eventually be reused for something else, overwriting the values stored in matches - and yes, that may well be why your application doesn't work - if it isn't right now, it probably will be once you have fixed some other problems, or changed it a bit, or something else, because this is not one of those little warnings that you can safely ignore.

You can fix this in a few different ways. The most obvious is to simply use std::vector<char *> [or better yet std::vector<std::string>] instead:

std::vector<std::string> ReadLineImpl::my_completion ()
{
    std::vector<std::string> strings;
    strings.push_back("add");
    return strings;
}

So, if the library requires a char ** as per the readline interface, then use this:

char** ReadLineImpl::my_completion ()
{
    char **matches = static_cast<char **>malloc(1 * sizeof(char *));
    matches[1] = "add";
    return matches;
}

Problem solved!

Cari answered 4/8, 2013 at 8:31 Comment(3)
I would use a vector as a c++ programmer but the library demands char**, so then I have to convert to char**.Volute
So, assuming you are using the readline interface, then you MUST allocate the memory with malloc, as readline frees it later. I will edit.Cari
Good, just one thing, I had to use (char**)malloc(1 * sizeof(char *)) but thanks, your answer is better, though I am not gonna changeVolute
B
2

Use the heap instead of the stack

It's better to allocate memory on the heap for this case by using:

int* someDataForParams(void *_params) {

    // ...

    int* charCounts = (int*) calloc(96, sizeof(char*));

    // ...

    return charCounts;
}

96 is just a string length (just a magic number).

Blondell answered 29/8, 2016 at 11:5 Comment(0)
W
2

There are two solutions:

The first one is to declare the variable as a static variable with the keyword static.

And the second solution is to use dynamic allocation with malloc or calloc.

Weirdie answered 24/1, 2022 at 16:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.