作为一个练习,我正在尝试一个二叉搜索树!
我已经创建了代码,它似乎在运行,但当我试图添加一个客户时,它崩溃了在调试代码之后,我在第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;
}
代码块调试器提供以下信息
活动调试器配置:GDB/CDB调试器:默认
确保来源最新的建筑物
选择目标:
调试
正在添加源目录:C:\调试\
正在添加源目录:C:\调试\
添加文件:C:\ debug\bin\debug\debug.exe
正在将目录更改为:C:/debug/。
Set变量:PATH=;C:\程序文件\CodeBlocks\MinGW\bin;C:\程序文件\CodeBlocks\MinGW;C:\ Windows\System32;C:\ Windows\System32\wbem;C:\ Windows\System32\WindowsPowerShell\v1.0;C:\程序文件\ATI技术\ATI.ACE\Core Static;C:\用户\baskon\AppData\Local\Microsoft\WindowsApps
正在启动调试器:C:\程序文件\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,位于C:\ debug\main.C:82的新BST_节点(根=0x0,l=0xbe0ec8)
C:\调试\main.C:82:1907:beg:0x401480
在C:\debug\main.C:82
9 0x00401480,位于C:\ debug\main.C:82的新BST_节点(根=0x0,l=0xbe0ec8)
C:\调试\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
被解析为空语句始终执行由{
引入的后续块。您可以避免这种愚蠢的错误,方法是始终对复合语句使用大括号,并将它们放在与语句开头相同的行上,而不是放在下一行上这与40多年前C语言创建者使用的原始K&R风格很接近。
函数
ch
中变量flush
的类型应为int
,以便正确区分getc()
返回的所有值:unsigned char
的所有值加上特殊值: void flush(void) {
int ch;
while ((ch = getchar()) != EOF && ch != '\n') {
continue;
}
}
请注意,您应该像我在上面所做的那样使空语句更加明确,以避免像前一个语句那样的混乱和错误。
您不应该使用过时的不安全函数:使用
EOF
并用gets()
删除后面的换行符。将字符串与
fgets()
进行比较时,应仅依赖返回值的符号在函数strcspn()
和strcmp()
中,与BST_find_customer()
进行比较:这是不可靠的改为使用new_BST_node()
。在函数
-1
中,在树中创建新节点时不返回if (strcmp(email, root->data->data->email) < 0)
以下是更正版本: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;
}
请注意,这是导致错误的原因,因为这里可能有无限递归。
最后有几条建议:
比较指针与空指针时,请使用
new_BST_node()
而不是root
它可读性更强。避免命名变量
NULL
,因为该名称在图形上与编程环境中使用的固定间距字体的0
太接近有时几乎无法区分。关于c - 使用malloc时出现段错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41780524/