6

I am trying to call a method that will generate a 2D char array (array of strings) and return it to be used in another function.

My example:

char ** example(void)
{
    char *test[3];

    int i;
    for (i = 0; i < 3; i++) {
        test[i] = malloc(3 * sizeof(char));
    }

    test[foo][bar] = 'baz'; // of course I would declare 'foo' and 'bar'
    // ...
    // ...

    return test;
}

And then I would like to be able to use the array as follows:

void otherMethod(void)
{
    char ** args = example();
    // do stuff with args
}

The problem is that this produces the error:

warning: address of stack memory associated with local variable 'test' returned [-Wreturn-stack-address]

I could solve this problem by defining test in the global scope as opposed to locally, but I would very much rather not do this as it seems messy, especially if I am to have several of these.

Is there a way to create and return an array of strings in C without defining it globally?

Cœur
  • 37,241
  • 25
  • 195
  • 267
tam5
  • 3,197
  • 5
  • 24
  • 45
  • Same error message: *[Using C-string gives Warning: "Address of stack memory associated with local variable returned"](https://stackoverflow.com/questions/18041100/)* – Peter Mortensen Oct 22 '22 at 05:04

4 Answers4

8

You are on the right track. All you need to do is to change the allocation of the test[3]; itself from automatic (aka "stack") to dynamic (aka "heap"):

char **test = malloc(3 * sizeof(char*));

This makes it legal to return test from your function, because it would no longer be returning an address associated with stack allocation.

Of course the caller would be required to free both the pointers inside the return, and the return itself. You may want to consider supplying a helper function for that.

Another approach would be to take char test[] as a function parameter:

void example(char *test[], size_t count) {
    for (size_t i = 0 ; i < count ; i++) {
        test[i] = malloc(3 * sizeof(char));
    }
    ...
    // return is not required
}

Now the caller would have to pass an array of suitable size into your function, so that you could avoid allocating it.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Using malloc:

char ** example(void)
{
    char** test = malloc(sizeof(char*) * 3);

    int i;
    for (i = 0; i < 3; i++) {
        test[i] = malloc(3 * sizeof(char));
    }

    test[foo][bar] = 'baz'; // of course I would declare 'foo' and 'bar'
    // ...
    // ...

    return test;
}
cadaniluk
  • 15,027
  • 2
  • 39
  • 67
1

Use static:

static char *test[3];
Sapphire_Brick
  • 1,560
  • 12
  • 26
0

This is mainly an addition to @dasblinkenlight's answer.

You write:

test[i] = malloc(3 * sizeof(char));

test[i] is now a char array that can contain a string of at most 2 characters and the terminating null. And you should load it that way:

strncpy(test[i], 2, str); /* where str is another char pointer */

So I would write:

test[i] = malloc(4 * sizeof(char));
strcpy(test[i], "baz");

C strings can be confusing at first sight ;-)

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252