使用malloc

时间:2017-01-21 14:28:40

标签: c segmentation-fault

作为练习,我正在尝试使用二进制搜索树!

我已经创建了代码并且似乎正在运行,但是当我尝试添加客户时它会崩溃。在调试代码之后,我在第82行得到了一个分段错误,我尝试将内存分配给root ...研究一段时间我发现它是与内存有关的东西,但无法计算出发生了什么我的代码...有关在尝试分配内存时导致此失败的原因的任何建议吗?

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

#define MAX_STRING 50

void flush();

struct customer {
    char *name;
    char *address;
    char *email;
};

struct double_linked_list {
    struct customer *data;
    struct double_linked_list *previous;
    struct double_linked_list *next;
};

struct double_linked_list *customers_head = 0;

struct BST_node {
    struct double_linked_list *data;
    struct BST_node *left;
    struct BST_node *right;
};

struct BST_node *BST_email_root = 0;

struct BST_node *BST_find_customer(struct BST_node *root, char *email) {
    if (root == NULL)
        return NULL;
    if (strcmp(email, root->data->data->email) == 0)
        return root;
    else {
        if (strcmp(email, root->data->data->email) == -1)
            return BST_find_customer(root->left, email);
        else
            return BST_find_customer(root->right, email);
    }
}

void find_customer() {
    char email[MAX_STRING];
    struct double_linked_list *l;
    struct BST_node *b;

    printf("Give the email of the customer (up to %d characters) : ", MAX_STRING - 1);
    gets(email);

    b = BST_find_customer(BST_email_root, email);
    if (b == 0)
        printf("There is no customer with this email.\n");
    else {
        l = b->data;
        printf("Customer found! \n");
        printf("Name    : %s\n", l->data->name);
        printf("Address : %s\n", l->data->address);
        printf("Email   : %s\n", l->data->email);
    }
}

struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l) {
    if (root == NULL);
    {
        root = (struct BST_node *)malloc(sizeof(struct BST_node));
        if (root == NULL) {
            printf("Out of Memory!");
            exit(1);
        }
        root->data = l;
        root->left = NULL;
        root->right = NULL;
    }

    if (strcmp(l->data->email, root->data->data->email) == -1)
        root->left = new_BST_node(root->left, l);
    else 
        root->right = new_BST_node(root->right, l);
    return root;
};

struct double_linked_list *new_customer() {
    char name[MAX_STRING], address[MAX_STRING], email[MAX_STRING];
    struct BST_node *b;
    struct double_linked_list *l;
    struct customer *c;

    printf("\nADDING NEW CUSTOMER\n=\n\n");
    printf("Give name (up to %d characters): ", MAX_STRING - 1);
    gets(name);

    printf("Give address (up to %d characters): ", MAX_STRING - 1);
    gets(address);

    printf("Give email (up to %d characters): ", MAX_STRING - 1);
    gets(email);

    b = BST_find_customer(BST_email_root, email);
    if (b) {
        printf("Duplicate email. Customer aborted.\n");
        return 0;
    }

    c = (struct customer *)malloc(sizeof(struct customer));
    if (c == 0) {
        printf("Not enough memory.\n");
        return 0;
    }

    c->name = strdup(name); // check for memory allocation problem
    if (c->name == 0)
        return 0;
    c->address = strdup(address);   // check for memory allocation problem
    if (c->address == 0)
        return 0;
    c->email = strdup(email);   // check for memory allocation problem
    if (c->email == 0)
        return 0;

    l = (struct double_linked_list*)malloc(sizeof(struct double_linked_list));
    if (l == 0) {
        printf("Not enough memory.\n");
        free(c->name);
        free(c->address);
        free(c->email);
        free(c);
        return 0;
    }

    l->data = c;
    l->previous = 0;
    l->next = customers_head;

    if (customers_head)
        customers_head->previous = l;

    customers_head = l;

    BST_email_root = new_BST_node(BST_email_root, l);

    return l;
}

void displaymenu() {
    printf("\n\n");
    printf("1. New customer\n");
    printf("2. Find customer using email\n");
    printf("0. Exit\n\n");
    printf("Give a choice (0-6) : ");
}

void flush() {
    char ch;
    while ((ch = getchar()) != '\n' && ch != EOF);
}

int main() {
    int choice;
    do {
        displaymenu();
        scanf("%d", &choice);
        flush();
        switch (choice) {
          case 1:
            new_customer();
            break;
          case 2:
            find_customer();
            break;
        }
    } while (choice != 0);

    return 0;
}

Codeblocks调试器提供以下信息

活动调试器配置:GDB / CDB调试器:默认

建立以确保来源是最新的

选择目标:

调试 添加源目录:C:\ debug \

添加源目录:C:\ debug \

添加文件:C:\ debug \ bin \ Debug \ debug.exe

将目录更改为:C:/ debug /.

设置变量:PATH =。; C:\ Program Files \ CodeBlocks \ MinGW \ bin; C:\ Program Files \ CodeBlocks \ MinGW; C:\ Windows \ System32; C:\ Windows; C:\ Windows \ System32 \ wbem; C:\ Windows \ System32 \ WindowsPowerShell \ v1.0; C:\ Program Files \ ATI Technologies \ ATI.ACE \ Core-Static; C:\ Users \ baskon \ AppData \ Local \ Microsoft \ WindowsApps

启动调试器:C:\ Program Files \ CodeBlocks \ MINGW \ bin \ gdb.exe -nx -fullname -quiet -args C:/debug/bin/Debug/debug.exe

完成

注册新类型:wxString

已注册的新类型:STL字符串

注册新类型:STL Vector

设置断点

调试器名称和版本:GNU gdb(GDB)7.6.1

子进程PID:5908

编程接收信号SIGSEGV,分段故障。

在?? ()()

9 0x00401480 in new_BST_node(root = 0x0,l = 0xbe0ec8)在C:\ debug \ main.c:82 C:\调试\ main.c中:82:1907:BEG:0x401480

在C:\ debug \ main.c:82

9 0x00401480 in new_BST_node(root = 0x0,l = 0xbe0ec8)在C:\ debug \ main.c:82 C:\调试\ main.c中:82:1907:BEG:0x401480

调用堆栈如下

enter image description here

2 个答案:

答案 0 :(得分:1)

您的代码中存在多个问题:

  • 你有一个经典的错误:

    struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l) {
    if (root == NULL);
    {
        root = (struct BST_node *)malloc(sizeof(struct BST_node));
    

    ;语句行末尾的if被解析为空语句。 <{1}}引入的后续块将始终执行。

    你可以通过总是使用复合语句的大括号并将它们放在与语句开头相同的行,的下一行来避免这种愚蠢的错误。这与40多年前C语言创作者使用的原始K&amp; R风格接近。

  • 函数{中变量ch的类型应为flush,以便正确区分int返回的所有值:{{1}的所有值加上特殊值getc()

    unsigned char

    请注意,您应该像我上面那样使空语句更加明确,以避免混淆和错误,例如前一个。

  • 您不应使用过时的不安全功能EOF:使用 void flush(void) { int ch; while ((ch = getchar()) != EOF && ch != '\n') { continue; } } 并使用gets()删除尾随换行符。

  • 将字符串与fgets()进行比较时,您应该只依赖于返回值的符号。在函数strcspn()strcmp()中,您与BST_find_customer()进行比较:这是不可靠的。请改用new_BST_node()

  • 在函数-1中,在树中创建新节点时,不返回if (strcmp(email, root->data->data->email) < 0)。这是一个更正版本:

    new_BST_node()

    请注意,这会导致您的错误,因为您可能会在此处进行无限递归。

  • 最后有几条建议:

    • 在比较指向空指针的指针时使用root而不是struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l) { if (root == NULL) { root = malloc(sizeof(*root)); if (root == NULL) { printf("Out of Memory!"); exit(1); } root->data = l; root->left = NULL; root->right = NULL; return root; } if (strcmp(l->data->email, root->data->data->email) < 0) { root->left = new_BST_node(root->left, l); } else { root->right = new_BST_node(root->right, l); } return root; } 。它更具可读性。
    • 避免命名变量NULL,因为此名称与编程环境中使用的固定间距字体在图形上过于接近0。有时它几乎无法区分。

答案 1 :(得分:0)

好的,所以经过测试后我发现了什么是错的然而我无法弄清楚为什么 .. 任何建议?? 我认为strcmp返回0或-1或1的值。 但是有问题,如果我没有完全定义如果strcmp == 1或strcmp == - 1 ...我有无限循环,因为它似乎(我使用printf命令查看发生了什么,我发现了这个错误..)

通过更改

struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l)
{
if (root==NULL)
    {
    root = (struct BST_node *) malloc (sizeof(struct BST_node ));
    if (root==NULL)
        {
        printf("Out of Memory!");
        exit(1);
        }
    root->data=l;
    root->left=NULL;
    root->right=NULL;
    }

    if (strcmp(l->data->email, root->data->data->email) == -1)
        root->left =new_BST_node(root->left,l);
    else 
        root->right =new_BST_node(root->right,l);

    return root;
};

struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l)
    {
    if (root==NULL)
        {
        root= (struct BST_node *)malloc(sizeof(struct BST_node ));
        if (root==NULL)
            {
            printf("Out of Memory!");
            exit(1);
            }

        root->data=l;
        root->left=NULL;
        root->right=NULL;
        }

    if ((strcmp(l->data->email, root->data->data->email))==-1)
                root->left =new_BST_node(root->left,l);
    else if ((strcmp(l->data->email, root->data->data->email)) ==1)
        root->right =new_BST_node(root->right,l);

    return root;
};

一切正常...... 但为什么其他代码没有用呢?我很确定它是相同的 ......