SIGSEGV, Сегментатион Фаульт с C ++ в Code:: Blocks

Я добавляю узлы к соединенному простому списку, узлы сохраняют два типа стоимости double.

Когда я отлаживаю программу в Code::Blocks у меня выходит ошибка, которую он говорит:

"Program received signal SIGSEGV, Segmentation fault." 

Потом он предупреждает меня в какой секции кода он обнаружил проблему, он, когда я пробую звонить в функцию, которая добавляет узел с другой, которая показывает, сколько раз будь должен делать это.

Отладчик показывает ошибку два раза и потом говорит, что программа упала. Эта ошибка не мешает тому, чтобы он скроллировал программу, но я думаю, что он вызывает, что какие-то последующие вещи не функционировали, как они были бы должны. Как он мог бы упорядочивать это?

Я продолжил рекомендацию снимания указателя как глобальная переменная, кроме того, что забочусь о деталях, чтобы избегать того, чтобы он был недействительным, ошибка длится, код идет так сейчас:

В main важные линии - следующие:

Nodo *cls_val;
Nodo *n0 = new Nodo;
cls_val = n0;
n0->info = "Inicio de la lista";
Rangos(cls_val);

Функция Rangosэто так:

void Rangos(Nodo *cb)
{
    double mini = 1;
    for(int i = 0; i < clss; i++)
    {
        cb = Agr_Rango(mini, mini+anch, cb);
        cb = cb->sig;
        mini += anch;
    }
}

В конце концов, знаменитая Agr_Rangos где - конфликтная линия:

Nodo* Agr_Rango(double mnm, double mxm, Nodo *cab)
{
    Nodo *ni, *ptr;
    ni = new Nodo;
    ni->mn = mnm;
    ni->mx = mxm;
    ptr = cab;
    if(ptr == NULL)
    {
        cab = ni;
    }
    else
    {
        while(ptr->sig != NULL) //Aquí señala el problema.
            ptr = ptr->sig;
        ptr->sig = ni;
    }
    return ptr;
}
1
задан 14.04.2016, 07:20
1 ответ

SIGSEGV это ошибка, которую система бросает, когда пробует соглашаться на не действительную память.

Здесь ты можешь видеть детали в MSDN (Английский язык) и здесь подробно опиши в Wikipedia.

Итак, тогда, когда ptr->sig копье SIGSEGV, переменная ptr укажи на не действительную память. Переменная ptr она была распределена в предыдущих линиях с контентом cls_val которая, ты упоминаешь о том, что это глобальная переменная.

Подтверди следующее:

  • cls_val она инициализировалась правильно перед тем, как быть использованной.
  • cls_val он содержит действительную стоимость во время того, чтобы быть распределенным в ptr.
  • cls_val он не обозначается в NULL, nullptr или 0 во время того, чтобы быть распределенным в ptr.
  • cls_val она не соглашена с другого трэда одновременно в доступ, реализованный с Agr_Rango.
  • cls_val она не путается с другой локальной переменной того же имени в другом контексте.

С другой стороны, предотврати использование глобальных переменных по мере возможности:

  • Они испытывают недостаток в местности: Код более легкий для того, чтобы быть понятым, когда Ваша область ограничена. Глобальные переменные могут быть прочитанными или измененными с любой части программы, это сложно размышлять на Вашем использовании или помнить все точки, в которых они используются.
  • Они испытывают недостаток в контроле доступа или проверке ограничений: Глобальная переменная может быть прочитанной или написанной с любой части программы, несколько правил относительно Вашего использования могут быть забытыми или нарушенными.
  • Проблемы скопления: Если глобальные переменные могут быть соглашенными с нескольких трэдов, необходимо синхронизировать их. Когда он занимается с модулями dinámicamente соединенные, что используют глобальные переменные, вытекающая система может не быть включенная страховка, когда модули это будут независимым способом.
  • Загрязнение области имен: Глобальные переменные находятся во всех контекстах. Ты можешь заканчивать тем, что используешь глобальную переменную, когда ты верил в то, что использовал локальную одну: или наоборот! (уже состойте из-за незнания, в том, чтобы писать плохо имя или в том, чтобы забывать создать локальную переменную). Кроме того, если ты соединишь модули с глобальными переменными, имя которых было равно, если тебе везет, у тебя будут ошибки соединенный..., если тебе не повезет редактор связей, он будет считать переменные той же самой даже, хотя это не было твое намерение.
  • Больше проблем в ссылке (на Английском языке): Я перевел точки, в которые он верил, что они были более значимыми для твоей проблемы.

Если ты хочешь более подробное решение, я боюсь, что мы будем нуждаться в полном коде.


Изданный

Проблема могла бы быть в функциях Rangos и Agr_Rango в котором ты перемещаешь указатель, который нужно использовать из-за копии; давайте видеть примером функцию Rangos (из-за того, что является короче):

void Rangos(Nodo *cb)
{
    double mini = 1;
    for(int i = 0; i < clss; i++)
    {
        cb = Agr_Rango(mini, mini+anch, cb);
        cb = cb->sig;
        mini += anch;
    }
}

Параметр cb это копия указателя cls_val, так что, когда ты это инициализируешь в стоимость Agr_Rango то, что ты изменяешь, не cls_val приходящий ученик, если не Ваша копия; чтобы добиваться функциональность того, чтобы ожидание ты был должен перемещать указатель в указатель или ссылку на указатель:

Nodo *cls_val;
Nodo *n0 = new Nodo;
cls_val = n0;
n0->info = "Inicio de la lista";
Rangos(&cls_val); // <--- pasar como PUNTERO!!

void Rangos(Nodo **cb) // <--- puntero a puntero
{
    double mini = 1;
    for(int i = 0; i < clss; i++)
    {
        *cb = Agr_Rango(mini, mini+anch, cb); // <-- modificar valor apuntado
        *cb = (*cb)->sig;                     // <-- modificar valor apuntado
        mini += anch;
    }
}

Я лично предпочитаю версию снабди ссылками в указатель:

Nodo *cls_val;
Nodo *n0 = new Nodo;
cls_val = n0;
n0->info = "Inicio de la lista";
Rangos(cls_val); // <--- No requiere cambio alguno

void Rangos(Nodo *&cb) // <--- referencia!
{
    double mini = 1;
    for(int i = 0; i < clss; i++)
    {
        cb = Agr_Rango(mini, mini+anch, cb); // <--- No requiere cambio
        cb = cb->sig;                        // <--- No requiere cambio
        mini += anch;
    }
}

Ты будешь должен делать это изменение так в Rangos как в Agr_Rango. Ты можешь видеть упрощенный пример того, что я думаю, что это твоя проблема здесь:

void puntero(int *parametro)
{
    parametro = new int{456};
}

void puntero_a_puntero(int **parametro)
{
    *parametro = new int{789};
}

void referencia_a_puntero(int *&parametro)
{
    parametro = new int{111};
}

int *p = new int{123};

// p no es mocificado, sigue apuntando al valor 123, no a 456
puntero(p);
// p es modificado por puntero, apunta al valor 789
puntero_a_puntero(&p);
// p es modificado por referencia, apunta al valor 111
referencia_a_puntero(p);

PD: Уже, который у моего примера есть leaks памяти, это только один пример.

0
ответ дан 24.11.2019, 14:36
  • 1
    Спасибо за этот такой подробный ответ. Intent и # 233; меняться немного c и # 243; я говорю, чтобы снимать этот указатель как глобальная переменная, и которая переходила к тому, чтобы быть парой и # 225; метр нескольких вызовов. Adem и # 225; s, сейчас я инициализирую список с узлом vac и # 237; или чтобы избегать того, чтобы ptr закончил тем, что указал на NULL, когда ему распределяется стоимость указателя, но продолжает появляться та же ошибка. Издавать и # 233; вопрос, чтобы показывать ново c и # 243; я говорю. – Karman 14.04.2016, 07:07

Теги

Похожие вопросы