简体   繁体   中英

I can't figure out why I'm getting a seg fault in my code

So I have this

void MovieGroup::add(Movie* m)
{
  cout << "Size = " << size << endl;
  if(size < MAX_COLLECTION){

    if(size == 0){
      collection[0] = m;
    }
    else{

      for(int i = 0; i<size; i++){

        if(collection[i]->getYear() >= m->getYear()){

          for(int j = size-1; j != i; j--){
            collection[j] = collection[j-1];
          }
          collection[i] = m;
          break;

        }

        else{
          collection[size] = m;
        }

      }
    }

  size++;

  }
}

Everytime I try running it, it gives me a segmentation fault. The purpose of this is to add a movie object to this collection, but sorted by year. I'm really not sure where I'm illegally accessing memory. Any help on this would be greatly appreciated.

Additional info : MAX_COLLECTION is set to 64, I'm trying to start from the back of the array to shift each object over by 1

The line collection[size] = m; is in the wrong place. It needs to be outside the loop.

Also, when you shift the elements around, you are losing some elements, because you don't shift them all, so you end up overwriting some of them instead.

Also, you should use return instead of break after you shift the elements, otherwise you would have to keep track of whether the loop does the shift so that code after the loop can act accordingly.

Try this instead:

void MovieGroup::add(Movie* m)
{
  cout << "Size = " << size << endl;
  if (size < MAX_COLLECTION) {
    for (int i = 0; i < size; ++i) {
      if (collection[i]->getYear() >= m->getYear()) {
        for (int j = size-1; j >= i; --j) {
          collection[j+1] = collection[j];
        }
        collection[i] = m;
        ++size;
        return;
      }
    }
    collection[size] = m;
    ++size;
  }
}

With that said, I would tweak the function a step further so there is only 1 point of insertion and increment rather than 2 points:

void MovieGroup::add(Movie* m)
{
  cout << "Size = " << size << endl;
  if (size < MAX_COLLECTION) {
    int index = size;
    for (int i = 0; i < size; ++i) {
      if (collection[i]->getYear() >= m->getYear()) {
        for (int j = size-1; j >= i; --j) {
          collection[j+1] = collection[j];
        }
        index = i;
        break;
      }
    }
    collection[index] = m;
    ++size;
  }
}

And then, I would suggest using standard algorithms instead of manual operations:

#include <algorithm>
#include <iterator>

void MovieGroup::add(Movie* m)
{
  cout << "Size = " << size << endl;
  if (size < MAX_COLLECTION) {
    auto collection_end = std::next(collection, size);
    auto iter = std::find_if(collection, collection_end,
      [=](Movie *movie){ return movie->getYear() >= m->getYear(); }
    );
    if (iter != collection_end) {
      std::copy_backward(iter, collection_end, collection_end + 1);
    }
    *iter = m;
    ++size;
  }
}

And then lastly, you may want to consider changing collection to a std::vector instead of a fixed-length array, then you can use std::vector::insert() and not worry about manually shifting elements or keeping track of the size :

#include <algorithm>

void MovieGroup::add(Movie* m)
{
  cout << "Size = " << size << endl;
  auto iter = std::find_if(collection.begin(), collection.end(),
    [=](Movie *movie){ return movie->getYear() >= m->getYear(); }
  );
  collection.insert(iter, m);
}

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