Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delete()函数中C中的分段错误(堆芯转储)_C_Linked List_Runtime Error_Nodes - Fatal编程技术网

Delete()函数中C中的分段错误(堆芯转储)

Delete()函数中C中的分段错误(堆芯转储),c,linked-list,runtime-error,nodes,C,Linked List,Runtime Error,Nodes,我正在用C语言编写一个使用链表的字典,我的所有函数都可以工作,除了我的delete函数,它与所有其他必要的代码一起显示在下面。每次我试图在程序到达必须删除节点的行时运行程序时,它都会给我一个错误:分段错误(内核转储),这意味着它与内存分配或空指针有关。我知道我其余的代码都能正常工作。感谢您的一切帮助!:) #包括 #包括 #包括 #包括 #包括“Dictionary.h” //NodeObj 类型定义结构节点bj{ 字符*键; 字符*值; 结构NodeObj*next; }NodeObj; //

我正在用C语言编写一个使用链表的字典,我的所有函数都可以工作,除了我的delete函数,它与所有其他必要的代码一起显示在下面。每次我试图在程序到达必须删除节点的行时运行程序时,它都会给我一个错误:分段错误(内核转储),这意味着它与内存分配或空指针有关。我知道我其余的代码都能正常工作。感谢您的一切帮助!:)

#包括
#包括
#包括
#包括
#包括“Dictionary.h”
//NodeObj
类型定义结构节点bj{
字符*键;
字符*值;
结构NodeObj*next;
}NodeObj;
//节点
typedef NodeObj*节点;
//newNode()
//节点类型的构造函数
节点newNode(字符*键,字符*值)
{
节点N=malloc(sizeof(NodeObj));
断言(N!=NULL);
//if(key!=NULL&&value!=NULL){
N->key=key;
N->value=value;
N->next=NULL;
//  }
返回(N);
}
//字典
typedef结构字典YOBJ{
节点头;
int numItems;
}字典YOBJ;
//新字典()
//字典类型的构造函数
字典新建字典(作废){
字典D=malloc(sizeof(DictionaryObj));
断言(D!=NULL);
D->head=NULL;
D->numItems=0;
返回D;
}
节点findKey(字典D,字符*键){
节点N;
N=D->head;
while(N!=NULL){
如果(strcmp(N->key,key)==0){
返回N;
}
N=N->next;
}
返回NULL;
}
字符*查找(字典D、字符*k){
if(findKey(D,k)==NULL){
返回NULL;
}否则{
节点N;
N=findKey(D,k);
返回N->value;
}
}
作废删除(字典D,字符*k)
{
if(查找(D,k)=NULL){
fprintf(标准,
“KeyNotFoundException:无法删除不存在的密钥\n”);
退出(退出失败);
}
int check=strcmp(D->head->key,k);
如果(检查==1){
D->head=D->head->next;
返回;
}
节点电流;
节点前置;
cur=D->head;
prev=NULL;
while(cur!=NULL){
int ret1;
ret1=strcmp(cur->key,k);
while(ret1==0){
prev=cur;
cur=cur->next;
}
}
上一步->下一步=当前->下一步;
D->numItems--;
}

节点对象应存储字符串副本并注意删除:

typedef struct Node Node;
struct Node {
    Node *next;
    char *key, *value;
};

Node* newNode(char* key, char* value) {
    assert(key && value);
    Node* node = (Node*)malloc(sizeof(Node));
    assert(node);
    node->next = NULL;
    node->key = strdup(key);
    node->value = strdup(value);
}
void delNode(Node* node) {
    free(node->key);
    free(node->value);
}
考虑在本场景中使用原始代码(不使用该
strdup
)o:

Node* prepare() {
    char key_buf[20]; strcpy(key_buf, "mykey");
    char val_buf[20]; strcpy(val_buf, "myval");
    return newNode(key_buf, val_buf);
}
void examine(Node* node) {
   printf("Node key=%s value=%s\n", node->key, node->value);
}
int main() {
    examine(prepare());
}

上面的代码将崩溃,因为节点将有指向堆栈的指针(在您的情况下没有
strdup
),但key_buf+val_buf仅在prepare()内部有效(外部垃圾,因此内部检查()-Node->指向随机数据的关键点)。

在调试器下运行此操作时,崩溃似乎发生在哪里?而且您没有提供重要的
Dictionary.h
。不管怎样,我的水晶球告诉我:
N->value=value是不好的。我相信您传递给值的字符串不是在调用方动态分配的。相反,我认为它可能是一个本地自动字符缓冲区,它被破坏了,留下一个字典,里面充满了悬空的值指针。dictionary.h只是定义了这里列出的函数,并在注释中说明了它们的作用。崩溃似乎源于函数delete(),可能在strcmp()区域1中。密钥+值存储在哪里?(我想你应该复印一份。您不应该将strcmp的结果与1进行比较(如果(check==1)),但要么是0,要么不是。我有另一个insert()未显示,它使用除delete()之外的所有列出的函数,并且工作正常,因此我认为该代码没有问题。。同样感谢firda,我将strcmp比较从检查1更改为0。另外,请,请,除非它是不透明的库“句柄”类型或函数指针typedef,否则请不要将指针隐藏在typedef别名中。它对清晰性没有任何作用,实际上使代码更难阅读。(顺便说一句,不铸造马洛克的道具)。
Node* prepare() {
    char key_buf[20]; strcpy(key_buf, "mykey");
    char val_buf[20]; strcpy(val_buf, "myval");
    return newNode(key_buf, val_buf);
}
void examine(Node* node) {
   printf("Node key=%s value=%s\n", node->key, node->value);
}
int main() {
    examine(prepare());
}