作为练习,我正在尝试在二叉搜索树上工作!
我已经创建了代码并且它似乎可以运行,但是当我尝试添加客户时它崩溃了。调试代码后,我在第 82 行遇到段错误,我尝试将内存分配给根...研究了一段时间,我发现它与内存有关,但无法弄清楚我的代码发生了什么...关于尝试分配内存时导致此失败的原因有什么建议吗?
#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 String
注册新类型: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:\debug\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:\debug\main.c:82:1907:beg:0x401480
调用栈如下
最佳答案
您的代码中存在多个问题:
这里有一个典型的错误:
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
的末尾语句行被解析为空语句。后续 block ,由{
引入将始终执行。您可以通过始终对复合语句使用大括号并将它们放在与语句开头相同的行而不是下一行来避免这种愚蠢的错误。这与 40 多年前 C 语言的创造者使用的原始 K&R 风格很接近。
变量类型
ch
在函数中flush
应该是int
允许正确区分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
将指针与空指针进行比较时。它更具可读性。 - 避免命名变量
l
因为这个名称在图形上太接近1
使用编程环境中使用的固定间距字体。有时几乎无法区分。
- 使用
关于c - 使用 malloc 时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41780524/