简体   繁体   中英

Segmentation fault using max_element() and min_element() in C++

When I try to run this program there is a segmentation fault that is caused in this section:

      std::vector<double> dist1(dist);

      dist1.erase(std::remove(dist1.begin(), dist1.end(), 0), dist1.end());

      max = *std::max_element(dist1.begin(),dist1.end());

      min = *std::min_element(dist1.begin(),dist1.end());

It is the use of the max_element() and min_element() that cause the segmentation fault but I do not see why. What I doing here is copying a vector "dist" to "dist1", removing all occurrences of "0" in the new vector and then searching for the minimum and maximum values from the remaining items in "dist" "max" and "min" are double type variables previously declared. "dist" is previously declared as

 std::vector<double> dist; //vector used to hold the distances between adjacent vertices

 dist.resize(size);

The code compiles otherwise with g++ on a Linux server. Please advice.

Most probably dist1 is empty after applying remove/erase operations.

In case of empty input interval std::min_element and std::max_element return the end of the input range. As a consequence you try to dereference dist1.end() and crash happens.

It is the use of the max_element() and min_element() that cause the segmentation fault but I do not see why.

No, it is the dereferencing of the result which causes the segmentation fault.

If you use those functions with an empty range, then the end iterator is returned. Any attempt to dereference that iterator is undefined behaviour. A segmentation fault is one typical but not necessary result of undefined behaviour.

You must either prevent your vector from being empty (and ideally add an assertion for that) or change your program logic to support an empty vector.

Option 1:

// code that prevents dist1 from being empty goes here
// ...
auto const max_iter = std::max_element(dist1.begin(), dist1.end());
assert(max_iter != dist1.end());
auto const max = *max_iter;

Option 2:

auto const max_iter = std::max_element(dist1.begin(), dist1.end());
if (max_iter == dist1.end())
{
    // do something to handle the special situation
}
else
{
    auto const max = *max_iter;
    // normal program flow
}

I found a way to get it to work. Instead of just using the copy constructor

std::vector<double> dist1(dist)

I also declared and resized my new vector as follows:

std::vector<double> dist1(size);
dist1=dist;

One thing that still bothers me: Shouldn't the copy constructor done all of this?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM