c - 在一个函数而不是另一个函数中访问同一内存时发生段错误

标签 c struct linked-list segmentation-fault

我正在用一堆 ListNodes 实现一个 LinkedList,这些 ListNodes 是包含一些关于人的基本信息的结构。我有两个文件,一个是 main.c,另一个是 main.h。每当我尝试通过将根传递给函数来打印列表时,我都会收到错误消息。

这是main.c:

#include "main.h"

/* Edward Nusinovich

    This C file is going to have a LinkedList containing information about people.
    The user can interact with it and manipulate the list.

*/

int main(int argc, char **argv){

    if(!checkIfValidArguments(argc).value){return -1;}

    ListNode *root = askForDetails(1,argv);
    ListNode *current = root;
    current->next = NULL;

    ListNode *temp;

    int index = 2;

    while(index<argc){
        temp = askForDetails(index,argv);
        current->next = temp;
        current = current->next;
        index++;
    }

    userLoop(root);

    return 0;
}

在我的 main.h 文件中,我在函数“userLoop”中打印 root 参数的属性没有问题,但是一旦我将 ListNode *root 传递给“print”或“stuff”,我就会遇到段错误尝试打印其值。

这是 main.h:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define true 1
#define false 0

typedef struct bool{
    int value:1;
} boolean;

//this is going to store info about a person
typedef struct people{

    char *name;
    char *hairColor;
    char *eyeColor;
    char *age;
    struct people *next;    

} ListNode;

//using a 1 bit bitfield we have constructed, stores whether or not the user has entered a proper number of inputs
boolean checkIfValidArguments(int numArgs){

    boolean validArguments;

    if(numArgs>1){validArguments.value=true;}
    else{validArguments.value=false; printf("We need some names of people.\n");}

    return validArguments;
}

//this will construct a new Person and return him to 
ListNode *askForDetails(int personIndex, char **argv){

    ListNode toReturn;

    char *name = argv[personIndex];
    printf("Please enter the hair color, eye color, and age of %s.\n",name);

    char *inBuf=malloc(100);
    char nextchar=getchar();
    int index = 0;

    if(nextchar!='\n'){inBuf[index]=nextchar; index++;}

    while((nextchar=getchar())!='\n'){
        inBuf[index] = nextchar;
        index ++;
    }

    toReturn.name = name;
    toReturn.hairColor = strtok(inBuf," ");
    toReturn.eyeColor = strtok(NULL," ");
    toReturn.age = strtok(NULL,"\n");

    ListNode *newNode = malloc(sizeof(ListNode)); 
    newNode = &toReturn;    
    return newNode;
}

char *getInput(char *message){

    printf("%s",message);
    char *inBuf = malloc(40);
    char nextchar=getchar();
    int index = 0;
    if(nextchar!='\n'){inBuf[index]=nextchar; index++;}

    while((nextchar=getchar())!='\n'){
        inBuf[index] = nextchar;
        index ++;
    }

    return inBuf;

}

void addToEnd(ListNode *root){

    ListNode *current = root;

    char *inBuf = getInput("\nEnter the name of a person who you want to add: \n"); 

    ListNode *toAdd = malloc(sizeof(ListNode));
    toAdd = askForDetails(0,&inBuf);
    toAdd->name = inBuf;
    toAdd->next = NULL;

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

    current->next = toAdd;
}


void print(ListNode *root){

    printf("The name is %s.\n",root->name);
/*
    ListNode *current = root;

    do{
        printf("\n%s's hair is %s, their eyes are %s and they are %s years old.\n",current->name,current->hairColor,current->eyeColor,current->age);
        current = current->next;
    }while(current!=NULL);
*/  

}

void remEnd(ListNode *root){

    ListNode *current = root;

    if(current == NULL){ return; }





}

void addAfter(ListNode *root){

    ListNode *current = root;

    char *name = getInput("\nWho do you want to add after?\n");
    int comparison = 0; 

    while(current!=NULL&&(comparison = strcmp(name,current->name))!=0){
        current = current -> next;
    }

    if(current==NULL){printf("\nIndividual not found.\n"); return;}

    else{
        char *newPerson = getInput("What's the name of the person you wish to add? ");

        ListNode *toAdd = askForDetails(0,&newPerson);
        ListNode *next = current->next;
        current -> next = toAdd;
        toAdd->next = next;
        return;
    }

}

void stuff(ListNode *root){
    printf("name is %s.\n",root->name);
    printf("Root lives at %u.\n",root);
}

void userLoop(ListNode *root){

    char input = ' ';

    printf("Root lives at %u.\n",root);

    while(true){
        printf("name is %s.\n",root->name);     

        if(input!='\n'){
            printf("\nWhat would you like to do with your list:\n");
            printf("A) Add an element at the end of the list\n");
            printf("B) Remove an element from the end of the list\n");
            printf("C) Add an element after an element on your list\n");
            printf("D) Print your list\n");
            printf("E) Quit this program\n\n");
        }

        input = getchar();

        switch(input){
            case 'A': addToEnd(root); break;            
            case 'B': remEnd(root); break;
            case 'C': addAfter(root); break;
            case 'D': stuff(root); break;
            case 'E': return;
        }
    }

}

当在两个函数中打印 root 内存中的地址时,我得到了相同的值,所以我不确定为什么我无法在一个函数而不是另一个函数中访问 root 中的值。

非常感谢您的帮助。

最佳答案

您似乎不太了解内存模型在 C 中的工作原理。您的违规代码可能是:

ListNode *newNode = malloc(sizeof(ListNode)); 
newNode = &toReturn;    
return newNode;

这会返回一个指向局部变量 toReturn 的指针,而不是 malloc 的内存地址。您需要将数据从 toReturn 复制到您的 malloc 内存空间中。但是,更糟糕的是,您没有为每个字符串分配空间,因此每个节点都指向相同的输入缓冲区。这应该可行,因为您为每个节点分配了 malloc,但是如果 你要开始删除节点管理你的内存会有点尴尬。您也不确定缓冲区中是否有足够的空间。

我建议查看一些在线资源(或者最好是一本书)以复习 C 内存的工作原理。

编辑:我没有在线学习 C,但快速谷歌搜索出现了 this , 乍一看似乎是一个不错的资源。

我建议查看 book list .我使用了 C Programming A Modern Approach。

关于c - 在一个函数而不是另一个函数中访问同一内存时发生段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36439806/

相关文章:

c - 使用 fscanf 读取 ASCII 码文件

c - 如何将可执行入口点的名称从 main 更改为其他名称?

c - C中的双向链表

c++ - 指向Linkedlist开头的指针正在更改,同时在末尾添加了新节点

c - 使用链表函数的内存范围

c - 解释器文件的主要用途是什么?

c++ - 类数组结构的填充

c++ - 使用 ctypes 将结构传递给 native 库时遇到问题

C 复制带有两个指针的链表

c - GMime 多部分内容