-1

I'm trying to return a pointer, that points to an array of strings, from a function and then access elements in the array that the returned pointer points to. I seem to get a pointer back from the function, but when I try to output individual elements of the array to the computer screen, my program seems to just stop outputting and end the program.

Running the code below, the pointer to the array outputs as expected (see screen output screenshot). However, when I try to access the array's elements, none of the elements are output to the screen and the program just ends. Any ideas/thoughts would be greatly appreciated. FYI, I realize that I'm not using the data that's being passed to the function, but that's because I'm trying to figure out how to access the data that gets returned first.

roster.h

#ifndef ROSTER_H
#define ROSTER_H

#include <iostream>
#include <string>

class Roster {
public:
    std::string* parseData(const std::string Data);
};

#endif

roster.cpp

#include <iostream>
#include <string>
#include "roster.h"

std::string* Roster::parseData(const std::string Data) {
    std::string stringData[3] = { "abc", "def", "ghi" };
    return stringData;
}

rostertest.cpp

#include <iostream>
#include <string>
#include "roster.h"

void rosterClassTest()
{
    Roster roster;

    std::string* returnData = roster.parseData("red,blue,black,gray");

    std::cout << "pointer returned: "
        << returnData << std::endl << std::endl;
    std::cout << "element 0 of array: "
        << returnData[0] << std::endl << std::endl;
    std::cout << "element 1 of array: "
        << returnData[1] << std::endl << std::endl;
    std::cout << "element 2 of array: "
        << returnData[2] << std::endl << std::endl;
}

screen output screenshot

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Mike
  • 1
  • 2
  • 1
    [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – Passerby Feb 22 '22 at 23:49
  • Your minimal example has evidence of an XY-problem. Show us code that you _actually_ intend to use. – Dúthomhas Feb 22 '22 at 23:50
  • Try declaring `stringData` as `static`, so it doesn't disappear after execution leaves the `parseData` function. – Thomas Matthews Feb 22 '22 at 23:53
  • 1
    Mike, it's not a good idea to ask the same question twice. Every question asked, deleted or not, is used to compute the quality of your contributions. You have three visible poorly (as in not upvoted) received questions and at least one deleted question. I don't know where the cut-off point is before the system stops accepting your questions, l but I do know that by the time most people reach that point they've dug too deep a hole to climb out of. You're going to have to be very choosy with the next few questions and make sure they are seen as a positive contribution. – user4581301 Feb 23 '22 at 00:00

1 Answers1

0

Roster::parseData() is returning a pointer to a local array variable that goes out of scope upon exit, destroying the array, and thus the function is returning a dangling pointer to invalid memory.

You should return a std::vector<std::string> (or std::array<std::string, 3>) instead, eg:

std::vector<std::string> Roster::parseData(const std::string Data) {
    std::vector<std::string> stringData{ "abc", "def", "ghi" };
    return stringData;
}
std::vector<std::string> returnData = roster.parseData("red,blue,black,gray");

std::cout << "pointer returned: " << returnData.data() << std::endl << std::endl;
for(size_t i = 0; i < returnData.size(); ++i) {
    std::cout << "element " << i << " of array: " << returnData[i] << std::endl << std::endl;
}

If that is not an option, then you will have to new[] the array, and then the caller will have to delete[] the array when finished using it, eg:

std::string* Roster::parseData(const std::string Data) {
    std::string *stringData = new std::string[3];
    stringData[0] = "abc";
    stringData[1] = "def";
    stringData[2] = "ghi";
    return stringData;
}
std::string* returnData = roster.parseData("red,blue,black,gray");

std::cout << "pointer returned: " << returnData << std::endl << std::endl;
std::cout << "element 0 of array: " << returnData[0] << std::endl << std::endl;
std::cout << "element 1 of array: " << returnData[1] << std::endl << std::endl;
std::cout << "element 2 of array: " << returnData[2] << std::endl << std::endl;

delete[] returnData;

In which case, you should return a std::unique_ptr instead, eg:

std::unique_ptr<std::string[]> Roster::parseData(const std::string Data) {
    //std::unique_ptr<std::string[]> stringData(new std::string[3]);
    auto stringData = std::make_unique<std::string[]>(3);
    stringData[0] = "abc";
    stringData[1] = "def";
    stringData[2] = "ghi";
    return stringData;
}
auto returnData = roster.parseData("red,blue,black,gray");

std::cout << "pointer returned: " << returnData.get() << std::endl << std::endl;
std::cout << "element 0 of array: " << returnData[0] << std::endl << std::endl;
std::cout << "element 1 of array: " << returnData[1] << std::endl << std::endl;
std::cout << "element 2 of array: " << returnData[2] << std::endl << std::endl;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770