0

I am trying to pass in a empty struct pointer into a function called "initialize" as an output parameter and then after the function finishes I could retrieve the object pointed by the struct pointer. Some unexpected behaviors occur and I don't quite understand.

Below is my code:

static void initialize(complex_struct*& infoPtr)
{
    complex_struct myInfo;
    infoPtr = &myInfo;
    // some other codes that modify the contents of myInfo
    infoPtr->input_components = 3;
}

static void myfunction()
{
    complex_struct* infoPtr = nullptr;
    initialize(infoPtr);
    std::cout << infoPtr->input_components << std::endl;
}

The output of this is an arbitrary large integer number. But I was expecting an integer 3 is printed.

Restrictions: I cannot modify complex_struct; it is a third_party struct that needs to be used. Also, the reason why I need initialize() to be a separate function is that I am doing performance measurement on the memory allocation of complex_struct. So moving the first line of code in initialize() to myfunction() is not an ideal solution.

1
  • You are returning (via the pointer reference) a pointer to a stack object that is initialized when initialize begins and is destructed when initialize ends. Stale pointer is a bad pointer. Commented Sep 30, 2015 at 20:18

2 Answers 2

6

You are trying to use the pointer to local variable outside of it's scope funciton. In your example, myInfo instance inside initialize() will be deleted after you exit the function, and the address you remembered will be pointing to random garbage memory. You should never use pointers to local variables outside of their scopes.

How to fix the issue? The easiest way would be to ditch the pointer here, and instead pass your struct by non-const reference. Code would look like following:

void initialize(complex_struct& info)
{
    // some other codes that modify the contents of myInfo
    info.input_components = 3;
}

void myfunction()
{
    complex_struct info;
    initialize(info);
    std::cout << info.input_components << std::endl;
}

There is one subtle flaw in the suggested code: effectively info is initialized twice. First time when it's instance is created (complex_struct info) and the second time inside initialize() function. It would not have any noticeable effect in this example (info is allocated on the stack, and I do not think it has any non-trivial constructor) but might be of bigger problem in other setting. The best way to initialize it in this case would be to return the struct from the initialzer function, and rely on copy-elision to optimize away all the copies. Illustration code:

complex_struct initialize()
{
    complex_struct info;
    // some other codes that modify the contents of myInfo
    info.input_components = 3;
    return info;
}

void myfunction()
{
    complex_struct info = initialize();
    std::cout << info.input_components << std::endl;
}
Sign up to request clarification or add additional context in comments.

Comments

2

You are returning a pointer to an object in the stack frame. That object gets deleted when the function returns. You have a dangling pointer in myfunction.

Ways to solve the problem:

Allocate memory from heap

static void initialize(complex_struct*& infoPtr)
{
    infoPtr = new complex_struct ;
    infoPtr->input_components = 3;
}

Make sure to deallocate the memory in the calling function.

Use an object, instead of a pointer

static void initialize(complex_struct& info)
{
    info.input_components = 3;
}

and change its usage:

static void myfunction()
{
    complex_struct info;
    initialize(info);
    std::cout << info.input_components << std::endl;
}

2 Comments

Does the line of code "complex_struct myinfo;" involve time-consuming memory allocation itself? I am trying to keep the memory allocation activities within the initialize() function so as to perform an accurate performance measurement.
I am guessing that you are asking whether that involves dynamic memory allocation. The answer to that is: no, it does not. That object is created using stack memory.

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.