【问题标题】:seg fault: Cannot access memory at address段错误:无法访问地址处的内存
【发布时间】:2017-08-28 11:14:38
【问题描述】:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

#define ALPHABET_LENGTH    26
#define OPERATION_BUF_SIZE  5
#define NAME_BUF_SIZE      22
#define MAX_BUF_SIZE       27

#ifndef NULL 
#define NULL ((void*)0) 
#endif

/* Basic trie node -- also, keep track of number of nodes below this one. */
typedef struct node {
    int num_children;
    struct node *children[ALPHABET_LENGTH];
} trie_node;

trie_node* init(trie_node* a) {
    a->num_children = 0;
    for (int i = 0; i < ALPHABET_LENGTH; ++i)
    {
        a->children[i] = NULL;
    }
    return a;
}

char* trim(char* a){
    if (a[0] == 'a')
    {
        a += 4;
    }else{
        a += 5;
    }
    return a;
}

void add(char* a, trie_node* node){//need to make sure a is not NULL at beginning
    trie_node* newNode = malloc(sizeof(struct node));
    newNode = init(newNode);
    int i;
    if ((a != NULL && a[0] !='\n') && node->children[a[0] - 97] == NULL)
    {
        node->num_children++;
        //initialize the children array
        for (i = 0; i < ALPHABET_LENGTH; i++)
        {
            if (newNode->children[i] != NULL)
            {
                newNode->children[i] = NULL;
            }
        }
        newNode -> num_children = 0;
        node->children[a[0] - 97] = newNode;
        a++;
        add(a, newNode);
    }
    else if ((a != NULL && a[0] !='\n') && node->children[a[0] - 97] != NULL){
        a++;
        node->num_children++;
        add(a, node->children[a[0] - 97]);
    } else{//a == NULL, which means end of the add procedure
        return;
    }
    free(newNode);
}

int main()
{
    int t,total,remain,temp;
    scanf("%d\n", &t);
    total = t;
    trie_node* contacts = malloc(sizeof(struct node));
    contacts = init(contacts);
    while(t != 0){
        char* s = malloc(MAX_BUF_SIZE); //char array to store the input
        t--;
        remain = total - t;
        fgets(s, MAX_BUF_SIZE, stdin);
        if (s[0] == 'a')
        {
            s = trim(s);
            //do add operation
            if (s != NULL)
            {//make sure there is something to add
                add(s, contacts);
            }

        }
        else{
            printf("No such operation found at line %d. (Only add or find is allowed)\n", remain);
        }
        free(contacts);
        free(s);//memory leak problem
    }

    //if operation is not add or find, will be an error.
    return 0;
}

每次我的程序在 add 函数中进入第二种情况,即 else if 语句时,它会出现段错误,说 node->children[a[0]-97] 无法访问。 例如,我先添加 abc,然后添加 acd。这将出现段错误。 另外,我相信我的函数中存在一些内存泄漏。我在 valgrind 中检查了我的代码。它说 free() 在 free(s) 处无效

对不起,我应该在开头提到这一点。 a 假设由小写字母组成。而我目前所有的测试输入,只考虑添加和查找操作。

【问题讨论】:

  • 如果 strlen(a) 恰好是 s = trim(s); 会做一些奇怪的事情。
  • if (s != NULL) 应该在fgets(s, MAX_BUF_SIZE, stdin); 之前检查
  • 顺便说一句,每次你创建一个newNode 然后你会在添加函数结束时释放,所以第二次内存不存在.....
  • s = trim(s); 后面不能是free(s);。因为它与malloc 的返回值不同。
  • free 必须应用。例如,您可以执行以下操作。 char* buff = malloc(MAX_BUF_SIZE);while(t != 0){ char* s = buff;... } free(buff);char buff[MAX_BUF_SIZE]; 而不是 char* buff = malloc(MAX_BUF_SIZE); Alos free(contacts); 移动到 while-loop 之后。让我们释放整个树。

标签: c memory memory-leaks segmentation-fault


【解决方案1】:

首先,感谢所有回答我问题的人。我函数中的真正问题是我在使用 a[0] 访问节点位置之前修改了 a。

这是我解决问题的方法:

void add(char* a, trie_node* node){//need to make sure a is not NULL at beginning
    int i,temp;
    if ((a != NULL && a[0] !='\n') && node->children[a[0] - 97] == NULL)
    {
        node->num_children++;
        //initialize the children array
        trie_node* newNode = malloc(sizeof(struct node));
        newNode = init(newNode);
        node->children[a[0] - 97] = newNode;
        a++;
        add(a, newNode);
    }
    else if ((a != NULL && a[0] !='\n') && node->children[a[0] - 97] != NULL){
        node->num_children++;
        temp = a[0];
        a++;
        add(a, node->children[temp - 97]);//line 56
    } else{//a == NULL, which means end of the add procedure
        return;
    }
}

我添加一个 int temp 来存储 a[0] 的值,然后执行 a++。

在我这样做之前,如果我“添加 abc”然后“添加 acd”,在第二个循环中,在第 56 行,添加函数将获取 a 的值作为“cd\n”,以及节点的值->children[a[0]-97] 其中 a[0] 现在是 c 而不是 a。

现在一切都已修复。谢谢大家!

【讨论】:

  • 还是问题,如果a[0]不是ascii小写字母怎么办?
  • char 指针 a 永远不会为 NULL,直到 a 递增,直到它循环回 0!我怀疑您正在寻找 NUL 字符串终止字节,因此您应该使用:(*a != '\0')(a[0] != '\0')(*a)
  • @user3629249 这不是一个真正的应用程序。因此,正如提到的问题,a 必须由小写字母组成。感谢您指出这一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 2013-02-18
  • 1970-01-01
  • 2017-02-28
  • 2013-10-30
  • 1970-01-01
相关资源
最近更新 更多