Как исправить «ошибку сегментации (сброс ядра)» в зависимости от размера

#c 11

#c 11

Вопрос:

Я создал класс «config», который содержит 12 значений bool, организованных в std::array. Класс имеет функцию «обледенения», которая возвращает двойное значение. Пытаясь упорядочить вектор из 2 ^ 12 (4096) конфигураций через std:: sort (содержащийся в #include ), используя написанный мной предикат, я получаю ошибку ошибки сегментации.

Уменьшение вектора до 205 (не на 1 больше) устраняет ошибку, но я не знаю почему. Если я сделаю вектор длиной 4096 и попытаюсь отсортировать только небольшую часть, он будет работать до тех пор, пока длина части не достигнет 175 . Сокращение вектора, например, до 1000, ограничивает частичную сортировку примерно до 20, прежде чем она выдаст ошибку сегментации.

 #include <array>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std; 

class config {
public: 
    config (){       //constructor, default
        array<bool,12> t;
        for (boolamp; b: t){
            b=false;
        }
        val=t;
        g=1;
    }
    config (const configamp; fro): val(fro.val){};   //copy constructor
    array<bool,12> get_val(){ return val; }  //returns the array
    void set_tf(int n, bool tf){ val[n]=tf; }  //sets a certain boolean     in the array to false/true
    void set_g(double d){ g=d; }  //this sets the constant for     calculation to a number
    void print(){
        cout<<"values: ";
        for (auto b: val){ cout<<b<<" "; }
        cout<<endl;
    }
    config amp; incr(int n=1){ //this increases the vector by 1 following the rules for binary numbers, but has the digits reversed
        for(int j=0; j<n; j  ){
            int i=0;
            bool out=false;
            while(val[i]==true){
                val[i]=false;
                i  ;
            }
            val[i]=true;
        }
        return *this;
    }   
    double energy(){
        int ct=0;
        int cf=0;
        for(auto b:val){ if(b==true){ ct  ; } else { cf  ; } }
        return (abs(ct-cf));
    }
    double icing(){        //here is the "value" for ordering purposes
        int n=0;
        for(int i=0; i<11; i  ){
            if(val[i]!=val[i 1]){ n  ; }
        }
        double temp=-g*n this->energy();
        return temp;
    }
private:
    array<bool,12> val;
    double g;
};

bool pred (config c1, config c2){ return c1.icing()>c2.icing(); }     //this sets the ordering predicate

template <typename T>    //this orders the vector
void csort (vector <T>amp; in){
    sort(in.begin(), in.end(), pred);
}

int main(){
    vector<config> v;
    for (int i=0; i<4096; i  ){ //cicle that creates a vector of successive binaries
        for(autoamp; c:v){
            c.incr();
        }
        config t;
        v.push_back(t);
    }
    sort(v.begin(), v.begin() 174, pred);   //this gives seg.fault when 175 
    csort(v);           //this gives segmentation fault when the vec is 206 long or longer
}
  

Я ожидал, что код упорядочит вектор, но он переходит в ошибку сегментации.

Ответ №1:

Ваша программа имеет неопределенное поведение в sort функции, потому что ваш предикат принимает config по значению, поэтому создаются копии, и в этом месте вызывается конструктор копирования, который копирует только массив val , но не g .

 bool pred (config c1, config c2){ return c1.icing()>c2.icing(); } 
//         takes by value, copy ctor is called 
config (const configamp; fro): val(fro.val){}; // only val is copied, g HAS GARBAGE VALUE
// icing in pred uses g !! - stric weak ordering is violated because g has GARBAGE VALUE
  

Исправление 1:
передача конфигурации с помощью const configamp; :

 bool pred (const configamp; c1, const configamp; c2){ return c1.icing()>c2.icing(); }
  

или исправить 2:
g инициализируется в конструкторе копирования:

 config (const configamp; fro): val(fro.val), g(fro.g){};
  

Комментарии:

1. Большое спасибо! Я пошел со вторым подходом, потому что первый дает проблемы, потому что функция обледенения не определена как const , поэтому она начинает выдавать «игнорирует ошибку квалификаторов [f-permissive]». Второй подход — хороший улов, спасибо! Дело в том, что сначала класс должен был быть упорядочен по энергии, затем были внесены некоторые изменения, которые привели к добавлению частного значения g и относительного термина. При этом я забыл добавить g в конструктор копирования и только добавил его в конструктор … :/ глупый я