Как исправить «ошибку сегментации (ядро сброшено)» в зависимости от размера - PullRequest
0 голосов
/ 13 апреля 2019

Я создал класс "config", который содержит 12 значений bool, организованных в массив std ::.У класса есть функция «обледенения», которая возвращает двойное значение.Попытка упорядочить вектор из 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 (bool& b: t){
            b=false;
        }
        val=t;
        g=1;
    }
    config (const config& 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 & 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>& 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(auto& 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 Ответ

0 голосов
/ 13 апреля 2019

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

bool pred (config c1, config c2){ return c1.icing()>c2.icing(); } 
//         takes by value, copy ctor is called 
config (const config& 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 config&:

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

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

config (const config& fro): val(fro.val), g(fro.g){};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...