我有以下用于在 bst 中插入节点的程序
#include <stdio.h>
#include <stdlib.h>
struct node {
int key;
struct node * left;
struct node * right;
};
struct node * insert(struct node *,int);
int main( int argc, const char *argv[]){
struct node *root= malloc(sizeof(struct node ));
int x;
if(root==NULL){
printf("mem error");
return;
}
root=NULL;
while(1){
fprintf(stdout, "Enter the value of data\n" );
fscanf(stdin,"%d",&x);
root=insert(root,x);
}
}
struct node * insert(struct node * root, int data ){
if(root==NULL){
struct node *root= malloc(sizeof(struct node ));
root->key = data;
printf("hiii\n");
root->left = NULL;
root->right = NULL;
return root;
}else{
if(root->key >= data){
root->left = insert(root->left,data);
}else if(root->key <= data){
root->right = insert(root->right,data);
}
return root;
}
}
它运行良好..但是如果我注释插入函数中的malloc行..它在获取第一个值后会给我一个段错误。这是怎么回事??
最佳答案
您不能在插入函数中注释 malloc-line。 malloc() 的用途是动态分配新内存,以便将新节点插入到链表中。
阅读:void* malloc (size_t size);
Allocate memory block
Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
所以假设如果您在 insert()
中注释/删除 malloc 行(阅读注释):
//struct node *root= malloc(sizeof(struct node ));
root->key = data; // here illegal operation
root->left = NULL; // here illegal operation
root->right = NULL; // here illegal operation
那么root
值将是垃圾,您将访问进程未分配的垃圾地址并执行读/写操作 - 内存非法操作。
您的代码将编译,因为从语法角度来看,代码是正确的,但在运行时操作系统将检测到非法内存访问并可以终止您的代码。 (有趣的是:当操作系统检测到进程对内存权限的侵犯时,对有效内存的无效访问会给出:SIGSEGV,对无效地址的访问会给出:SIGBUS)。 --实际上这会导致未定义的行为。在最坏的情况下,您的程序可能看起来执行时没有任何失败,从而产生垃圾结果。
it gives me a segmentation fault after taking the first value. what is going on here?
正如我上面所解释的,删除 malloc()
会使您的程序以未定义的方式运行(阅读: Undefined behaviour )。如果程序以未定义的行为运行,您可以猜测会发生什么,在最坏的情况下,您的程序可能会执行而没有任何失败,或者可能会部分运行(这就是您所观察到的)。事情是,当操作系统检测到非法内存访问并发送信号来终止进程时。 (可能是root
的前五个随机垃圾值指向与我们的程序关联的内存,并且根据操作系统对该内存的访问不是非法操作符 - 而的第五次随机值root
是不属于操作系统检测到的进程和对该内存的读/写操作的内存,因此您的代码最终因段错误而终止)。
关于将数据复制到 c 中的节点值会导致段错误,但 malloc 将其删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17886228/