分段错误 - 从指针到指针的printf值

时间:2014-01-07 15:46:06

标签: c++ c struct

我试图在这里找到问题 - 在这个函数中:

void PrintDic(dictionary **head)
    {
        dictionary *current = *head;
        if(current->nexdic==NULL)
            printf("empty dictionary\n");
        else
        {
            while(current->nexdic!=NULL)
            {
                int i;
                for(i=0;i<1; i++)
                    printf("%s\n",current->word);
                current=current->nexdic;
            }
        }
    }

在Visual Studio中它可以工作,但在Linux中它总是给我一个分段错误。

结构:

struct dictionary
{
    char word[MAXLETTERS];
    char** year;
    int countyear;
    char** synonyms;
    int countsyn;
    char** def;
    int countdef;
    struct dictionary*nexdic;

};

添加功能:(将值插入结构并以字典方式查找地点以添加struct =链接列表!)

void Add(char* word, char * year,int countyear, char*syn, int countsyn, char* def,int countdef, dictionary** head)
{
    dictionary*next;
    //add new entry
    dictionary*newentry=(dictionary*)malloc(sizeof(dictionary));
    if(CheckNull(newentry)==1)
        exit(1);
    int i;
    char *index;
    //insert word
    strcpy(newentry->word,word);
    //insert year
    char **toyear=(char **)malloc((countyear+1)*sizeof(char*));
    index=year;
    for(i=0;i<=countyear; i++)
    {
        toyear[i]=index;
        index=NextString(index);
    }
    newentry->year=toyear;
    //insert syn 
    index=syn;
    char **tosyn=(char **)malloc((countsyn+1)*sizeof(char*));
    for(i=0;i<=countsyn; i++)
    {
        tosyn[i]=index;
        index=NextString(index);
    }
    newentry->synonyms=tosyn;
    //insert definition
    index=def;
    char **todef=(char **)malloc((countdef+1)*sizeof(char*));
    for(i=0;i<=countdef; i++)
    {
        todef[i]=index;
        index=NextString(index);
    }
    newentry->def=todef;
    //set counts
    newentry->countyear=countyear+1;
    newentry->countsyn=countsyn+1;
    newentry->countdef=countdef+1;
    next=FindPlace(newentry->word,*head);
    if(next==NULL)
    {
        if(*head==NULL)
            newentry->nexdic=NULL;
        else
        {
            newentry->nexdic=*head;
        }
        *head=newentry;
    }
    else
    {
        newentry->nexdic=next->nexdic;
        next->nexdic=newentry;
    }
}

2 个答案:

答案 0 :(得分:0)

下面的代码问题。

在while循环中,您的current变为current->nexic,但这不能NULL。对于下一次迭代,同时尝试访问您的current (current->nexdicNULL,从而导致段错误。

    while(current->nexdic!=NULL)
    {
        int i;
        for(i=0;i<current->countdef; i++)
            printf("%s\n",current->def[i]);
        current=current->nexdic;
    }

我不知道你的程序逻辑,但你可以检查while(current != NULL)而不是current->nexdic

答案 1 :(得分:0)

此代码似乎有效(在Mac OS X 10.9.1上使用GCC 4.8.2进行测试):

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

enum { MAXLETTERS = 32 };

typedef struct dictionary
{
    char word[MAXLETTERS];
    char **year;
    char **synonyms;
    char **def;
    int countyear;
    int countsyn;
    int countdef;
    struct dictionary *nexdic;
} dictionary;

static void PrintDic(dictionary **head)
{
    dictionary *current = *head;
    while (current != NULL)
    {
        printf("%s\n", current->word);
        current = current->nexdic;
    }
}

static int CheckNull(dictionary *dict)
{
    return dict == 0;
}

static char *NextString(char *str)
{
    return strchr(str, ',');
}

static dictionary *FindPlace(char *word, dictionary *head)
{
    printf("FP: (%p) [%s]\n", (void *)head, word);
    dictionary *ohead = 0;
    while (head != 0 && printf("HW: (%p) [%s]\n", head, head->word) > 0 && strcmp(head->word, word) < 0)
    {
        ohead = head;
        head = head->nexdic;
    }
    printf("FP: (%p)\n", (void *)ohead);
    return ohead;
}

static void Add(char *word, char *year, int countyear, char *syn, int countsyn,
                char *def, int countdef, dictionary **head)
{
    // Create new entry
    // add new entry
    dictionary *newentry = (dictionary *)malloc(sizeof(dictionary));
    if (CheckNull(newentry) == 1)
        exit(1);
    int i;
    char *index;
    // insert word
    strcpy(newentry->word, word);
    // insert year
    char **toyear = (char **)malloc((countyear + 1) * sizeof(char *));
    index = year;
    for (i = 0; i <= countyear; i++)
    {
        toyear[i] = index;
        index = NextString(index);
    }
    newentry->year = toyear;
    // insert syn
    index = syn;
    char **tosyn = (char **)malloc((countsyn + 1) * sizeof(char *));
    for (i = 0; i <= countsyn; i++)
    {
        tosyn[i] = index;
        index = NextString(index);
    }
    newentry->synonyms = tosyn;
    // insert definition
    index = def;
    char **todef = (char **)malloc((countdef + 1) * sizeof(char *));
    for (i = 0; i <= countdef; i++)
    {
        todef[i] = index;
        index = NextString(index);
    }
    newentry->def = todef;
    // set counts
    newentry->countyear = countyear + 1;
    newentry->countsyn = countsyn + 1;
    newentry->countdef = countdef + 1;

    // Insert new entry in correct place
    dictionary *next = FindPlace(newentry->word, *head);
    printf("Next = %p; head = %p\n", (void *)next, (void *)*head);
    if (next == NULL)
    {
        printf("-1-\n");
        newentry->nexdic = *head;
        *head = newentry;
    }
    else
    {
        printf("-2-\n");
        newentry->nexdic = next->nexdic;
        next->nexdic = newentry;
    }
}

int main(void)
{
    char line[4096];
    dictionary *head = 0;
    while (fgets(line, sizeof(line), stdin) != 0)
    {
        size_t offset = 0;
        char word[4096];
        int nchars;
        line[strlen(line)-1] = '\0';
        printf("Line: [%s]\n", line);
        while (sscanf(line + offset, "%s%n", word, &nchars) == 1)
        {
            printf("Word: [%s]\n", word);
            char *years = "1990,1999";
            char *syns = "a,z";
            char *defs = "definition1,definition2";
            printf("Old Head = %p\n", head);
            Add(word, years, 2, syns, 2, defs, 2, &head);
            PrintDic(&head);
            printf("New Head = %p\n", head);
            offset += nchars;
        }
    }
    return 0;
}

除了编写缺少的函数,如FindPlace()CheckNull()NextString()(以及测试驱动程序main()),并定义FindPlace()返回NULL当新节点应该位于列表的头部时,否则应该在返回的节点指针之后立即插入新节点,主要更改是处理“在头部插入”的代码,该代码比它需要的更复杂成为。 for中有一个有趣的单周期PrintDic()循环,现在已不复存在。您通过包括年份,同义词和定义信息使这个过程对我们感到不舒服,这可能对手头的问题不重要。司机会做最简单的事情。请注意,它不会将传递给Add()的字符串拆分,因此第一年条目会打印所有内容,第二年打印除第一年之外的所有字符串,依此类推,同样适用于同义词和定义。在每种情况下,列表项以逗号分隔。

有大量的调试打印代码;欢迎你删除它。

示例输出:

ggg
Line: [ggg]
Word: [ggg]
Old Head = 0x0
FP: (0x0) [ggg]
FP: (0x0)
Next = 0x0; head = 0x0
-1-
ggg
New Head = 0x7f848bc038b0
fff
Line: [fff]
Word: [fff]
Old Head = 0x7f848bc038b0
FP: (0x7f848bc038b0) [fff]
HW: (0x7f848bc038b0) [ggg]
FP: (0x0)
Next = 0x0; head = 0x7f848bc038b0
-1-
fff
ggg
New Head = 0x7f848bc03960
ccc
Line: [ccc]
Word: [ccc]
Old Head = 0x7f848bc03960
FP: (0x7f848bc03960) [ccc]
HW: (0x7f848bc03960) [fff]
FP: (0x0)
Next = 0x0; head = 0x7f848bc03960
-1-
ccc
fff
ggg
New Head = 0x7f848bd00000
ddd
Line: [ddd]
Word: [ddd]
Old Head = 0x7f848bd00000
FP: (0x7f848bd00000) [ddd]
HW: (0x7f848bd00000) [ccc]
HW: (0x7f848bc03960) [fff]
FP: (0x7f848bd00000)
Next = 0x7f848bd00000; head = 0x7f848bd00000
-2-
ccc
ddd
fff
ggg
New Head = 0x7f848bd00000
eee
Line: [eee]
Word: [eee]
Old Head = 0x7f848bd00000
FP: (0x7f848bd00000) [eee]
HW: (0x7f848bd00000) [ccc]
HW: (0x7f848be00000) [ddd]
HW: (0x7f848bc03960) [fff]
FP: (0x7f848be00000)
Next = 0x7f848be00000; head = 0x7f848bd00000
-2-
ccc
ddd
eee
fff
ggg
New Head = 0x7f848bd00000
aaa
Line: [aaa]
Word: [aaa]
Old Head = 0x7f848bd00000
FP: (0x7f848bd00000) [aaa]
HW: (0x7f848bd00000) [ccc]
FP: (0x0)
Next = 0x0; head = 0x7f848bd00000
-1-
aaa
ccc
ddd
eee
fff
ggg
New Head = 0x7f848be000b0
bbb
Line: [bbb]
Word: [bbb]
Old Head = 0x7f848be000b0
FP: (0x7f848be000b0) [bbb]
HW: (0x7f848be000b0) [aaa]
HW: (0x7f848bd00000) [ccc]
FP: (0x7f848be000b0)
Next = 0x7f848be000b0; head = 0x7f848be000b0
-2-
aaa
bbb
ccc
ddd
eee
fff
ggg
New Head = 0x7f848be000b0
zzz 
Line: [zzz]
Word: [zzz]
Old Head = 0x7f848be000b0
FP: (0x7f848be000b0) [zzz]
HW: (0x7f848be000b0) [aaa]
HW: (0x7f848bc03a10) [bbb]
HW: (0x7f848bd00000) [ccc]
HW: (0x7f848be00000) [ddd]
HW: (0x7f848bf00000) [eee]
HW: (0x7f848bc03960) [fff]
HW: (0x7f848bc038b0) [ggg]
FP: (0x7f848bc038b0)
Next = 0x7f848bc038b0; head = 0x7f848be000b0
-2-
aaa
bbb
ccc
ddd
eee
fff
ggg
zzz
New Head = 0x7f848be000b0