Не могу найти ошибку сегментации в моем коде - PullRequest
0 голосов
/ 31 мая 2018
#include <stdio.h>
#include <stdlib.h>

typedef struct node{
    struct node* next;
    int value;
}Node;

int findLastNodeValue(Node* head){
     while(head -> next != NULL){
         head = head -> next;
     }
         return head -> value;
}


int main(){
    Node  *node1,node2;
    node1 = (Node   *)malloc(sizeof(Node);
    node2 = NULL;
    node1 -> next = node2;
    findLastNodeValue(node1);
    findLastNodeValue(node2);
    return 0;
}

Этот код дает ошибку сегментации.Но я не могу найти, почему это происходит.Можете ли вы помочь мне с этим.

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Есть несколько проблем с вашим кодом:

  • Вы malloc ing node1, но вы нигде не устанавливаете значение.Это создает неопределенное поведение всякий раз, когда вы пытаетесь получить доступ к value - вы можете аварийно завершить работу программы или получить ненужные данные, что, как правило, хуже, поскольку это приводит к тому, что другие части вашего кода ведут себя странно.

  • Вы не освобождаете динамически выделенную память.Хотя в вашем случае это не такая уж большая проблема, это говорит мне, что вы не знакомы с тем, как работает динамическое распределение (мое убеждение также усиливается первым пунктом в этом списке).Всякий раз, когда вы malloc что-то, всегда free это (в C ++ у вас есть new и delete) и (для предотвращения непредвиденного поведения) установите указатель на NULL.

  • node2 не является указателем.* в Node *node1, node2; применяется только к первой переменной.Каждая последовательная переменная также нуждается в *, в противном случае она будет размещена в стеке.

  • Из анализа вашего кода становится ясно, что вы хотите, чтобы node2 был указателем (в противном случае выне будет присваивать NULL в качестве значения :)).В этом случае вы пытаетесь получить доступ к next из node2, но node2 инициализируется как NULL:

    int findLastNodeValue(Node* head){ // You are passing node2, which is NULL
        while(head -> next != NULL){ // Can't access next of a NULL -> code breaks
            head = head -> next;
        }
    
        return head -> value;
    }
    

Как правило, выполните следующие действия:

  • Попробуйте использовать функцию, которая создает экземпляр вашего узла - поскольку это C, у вас нет конструктора, я бы посоветовал написать функцию (или несколько, в зависимости от того, сколько функциональности вам нужно), который генерирует новый узел.Таким образом, вы гарантируете, что, по крайней мере, нет шансов не инициализировать узел

    Например:

    Node* createNode(int value) {
        Node* node = (Node *)malloc(sizeof(Node));
        if (!node) return NULL; // If malloc fails for some reason
        node -> value = value;
        node -> next = NULL;
    
        return node;
    }
    
  • Попробуйте использовать функцию, которая удаляет ваш узел -если есть шанс снова получить доступ к удаленной ссылке, установите для нее значение NULL и соответственно обработайте значение NULL

    Например:

    void deleteNode(Node** node) {
        if (!*node) return;
    
        free(*node);
        *node = NULL;
    }
    

    Обратите внимание, что приведенный выше код нене удаляйте ссылку на next, так как мы хотим удалить только тот узел, который передаем функции.Если у вас есть previous (в случае двойного связанного списка), вам сначала нужно получить доступ к узлу next, установить его значение previous равным NULL, а затем удалить текущий узел.

  • Всякий раз, когда вы передаете указатель, всегда проверяет, равен ли этот указатель NULL, прежде чем что-либо делать с данными, на которые он якобы ссылается.Комбинируя это с функцией создания узла с первой точки, вы можете быть уверены, что не передаете какой-то указатель Node, который не был правильно инициализирован

Теперь о вашей функции в частностиЯ бы сделал следующее:

int findLastNodeValue(Node* head) {
     if (!head) return -1; // We have a null reference, so there is nothing else to do here; exit accordingly and check the return value to see if the function call has been successful

     while(head -> next != NULL) {
         head = head -> next;
     }

     return head -> value;
}
0 голосов
/ 31 мая 2018

findLastNodeValue (node2) - ваша самая большая проблема.Когда вы отправляете NULL в findLastNodeValue, самое первое, что вы пытаетесь сделать, это разыменовать указатель NULL в предложении (head -> next! = NULL).

Чтобы решить эту проблему, вы можете проверить и обработатьслучай, когда head равен NULL в вашей функции findLastNodeValue перед вашим циклом while.

...