Home > Blockchain >  C : use std::string returned by a function: Using pointer to local variable that is out of scope
C : use std::string returned by a function: Using pointer to local variable that is out of scope

Time:11-05

I've got the following function:

MyFunction(const char *value, bool trigger) {
if (trigger) {
     std::string temporaryString = getTemporaryStringFromSomewhereElse();
     value = temporaryString.c_str();
}
// do processing here
// I need `value` and `temporaryString.c_str();` to be alive and accessible here and not destroyed

MyClass *object = new MyClass(value);
object->Work();
/// etc..

}

So, the question is how can I "prolong" the lifecycle of the temporaryString outside of the scope of the if-clause.

Currently, I'm getting the following error:

Using pointer to local variable 'temporary' that is out of scope.

I understand this is related to the memory management and the fact that the temporary is assumed to be "destroyed" or cleared from the memory after the if-clause. But I need to either prolong it's life cycle or to create another string (copy) which will have a different, wider scope.

How can I achieve this?

Requirements:

  1. Function signature cannot change, it should remain: MyFunction(const char *value, bool trigger)
  2. I use the value later on to initialize another object, do some other work. I cannot have 2 variables, e.g. value and anotherValueToBeUsedIfTriggerIsTrue.

CodePudding user response:

I prefer std::optional in that case as it also shows if the requested object was set or not.

Example:

std::string getTemporaryStringFromSomewhereElse()
{
    return "Here I am";
}

std::optional< std::string > MyFunction(bool trigger) {
    if (trigger) {
        return getTemporaryStringFromSomewhereElse();
    }   

    return std::nullopt;
}

int main()
{
    auto retval = MyFunction( true );
    if ( retval )
    {   
        std::cout << *retval << std::endl;
    }   
}

EDIT: ( After we got the info that the interface is not changeable )

This ends up in the question of ownership!

Who will allocate the memory of the passed string and who is responsible to free that memory.

Options:

  1. Allocate enough space and pass the pointer to that memory to the function and copy the content if trigger is set or set first char of memory to zero to show you pass back an empty string. If also an empty string is possible, use e.g. the first or last memory element as flag.
  2. Allocate the memory inside the function and copy the given string and pass back the pointer or return nullptr if trigger was not set. Caller of the function must deal with freeing the given memory.
  3. If it is guaranteed that the function will not be called again between the first call and the usage of the content, the function itself can keep a static array and pass back the address to that static memory.

BTW: Keeping broken interfaces is a good start point for bad software :-) In the given case if also empty strings are valid, you start hacking with flags in arrays and all that broken stuff ( normally we should use structs with flags in it as already defined with std::optional ).

CodePudding user response:

static storage is probably what you are searching for. static attribute to a variable extends its life time to the whole program execution time.

void MyFunction(const char *value, bool trigger) {
    if (trigger) {
        static std::string s_buffer; // Note : this line is executed only once so don't assign the value here
        s_buffer = getTemporaryStringFromSomewhereElse();
        value = s_buffer.c_str();
    }
    // use of value is still correct even outside the if statement.
}

Note : in case of multi threading programs use of static isn't thread safe, for this porpose the standard provides thread_local storage.

  • Related