Robert Kraaijeveld
Robert Kraaijeveld

Reputation: 695

C++ cannot acces vector elements when vector is returned from other method

I have the following code, which iterates over the result of a vector of pqxx::result rows.

std::unique_ptr<std::vector<pqxx::result::tuple>>
  filteredRowsPtr = getFilteredAssignmentRowsPtr(unfilteredRows);

std::vector<pqxx::result::tuple> filteredRows = *filteredRowsPtr;

for(int i = 0; i < filteredRows.size(); i++)
{
  returnMap[occurenceStudentIdStr] = returnMap[occurenceStudentIdStr] + 1; 
    pqxx::result::tuple currRow = filteredRows[i];

    for(int j = 0; j < currRow.size(); j++)
    {
        std::cout << "j = " << currRow[j] << endl;        
    }
}

filteredRowsPtr is a unique_ptr to a vector<pqxx::result::tuple> which is produced by the following method:

std::unique_ptr<std::vector<pqxx::result::tuple>> 
CompletedExcersisesPerStudent::getFilteredAssignmentRowsPtr(pqxx::result unfilteredRows)
{
    std::vector<pqxx::result::tuple> rowsFilteredOnGradePercentile = filter.getRowsWithValidGradePercentile(unfilteredRows);
    std::vector<pqxx::result::tuple> filteredRows = filter.getRowsWithValidAssignmentTimes(rowsFilteredOnGradePercentile);

    return std::make_unique<std::vector<pqxx::result::tuple>>(filteredRows);
} 

The vector is filled (since calling size() on it returns a positive number) and I can iterate over it fine, but when I try to actually access the elements contained in the row using

currRow[j]

I get a segmentation fault.

However: When I replace the call to getFilteredAssignmentsRowPtr() with the following, thusly replacing the contents of that method:

std::vector<pqxx::result::tuple> rowsFilteredOnGradePercentile = filter.getRowsWithValidGradePercentile(unfilteredRows);
std::vector<pqxx::result::tuple> filteredRows = filter.getRowsWithValidAssignmentTimes(rowsFilteredOnGradePercentile);

The expected result is outputted without any segfaults.

What am I doing wrong? Thanks in advance!

Upvotes: 0

Views: 80

Answers (2)

Robert Kraaijeveld
Robert Kraaijeveld

Reputation: 695

I fixed the issue by changing getFilteredAssignmentRows to return a vector instead of a unique ptr like you suggested, as well as passing a reference to a pqxx::result to getFilteredAssignmentRows like so:

std::vector<pqxx::result::tuple> CompletedExcersisesPerStudent::getFilteredAssignmentRowsPtr(pqxx::result& unfilteredRows)
{
    std::vector<pqxx::result::tuple> rowsFilteredOnGradePercentile = filter.getRowsWithValidGradePercentile(unfilteredRows);
    return filter.getRowsWithValidAssignmentTimes(rowsFilteredOnGradePercentile);
} 

This works since filter.getRowsWithValidGradePercentile is defined to take a reference to pqxx::result instead of a pqxx::result itself.

I must have accidentaly mis-read this.

Thanks a lot all the same!

Upvotes: 0

Walter
Walter

Reputation: 45444

Your error appears not reproducible (as you failed to provide a Minimal Verifiable Complete Example), but your design is flawed anyway: don't use a std::unique_ptr<std::vector>. std::vector already supports memory management, so you don't need to add that with a unique_ptr. IHMO, the correct design would be more like

std::vector<pqxx::result::tuple>
getFilteredAssignmentRowsPtr(pqxx::result unfilteredRows)
{
  return filter.getRowsWithValidAssignmentTimes(
         filter.getRowsWithValidGradePercentile(unfilteredRows));
} 

auto filteredRows = getFilteredAssignmentRowsPtr(unfilteredRows);

for(int i = 0; i < filteredRows.size(); i++)
{
  returnMap[occurenceStudentIdStr] = returnMap[occurenceStudentIdStr] + 1; 
  auto currRow = filteredRows[i];

  for(int j = 0; j < currRow.size(); j++)
  {
     std::cout << "j = " << currRow[j] << endl;        
  }
}

Upvotes: 1

Related Questions