C 是否从上到下读取代码

C 是否从上到下读取代码,c,pointers,crash,C,Pointers,Crash,我正在用c语言创建一个基于链表的程序,其中(struct的)每个节点都有一个整数和一个指向下一个节点的指针 在添加新节点和删除旧节点时,我使用动态分配(malloc)和释放(free) 删除节点时,将调用名为delete的函数 我发现,当调用这个delete函数时,程序有时会崩溃,我知道它与方法中的指针有关,但我不知道代码中的什么地方(行号)以及为什么会发生这种情况 我习惯于使用Java等高级语言,我习惯于通过在方法中的某些位置放置打印语法来解决问题,只是为了揭示它崩溃的地方。 我想我可以用c和

我正在用c语言创建一个基于链表的程序,其中(struct的)每个节点都有一个整数和一个指向下一个节点的指针

在添加新节点和删除旧节点时,我使用动态分配(malloc)和释放(free)

删除节点时,将调用名为delete的函数

我发现,当调用这个delete函数时,程序有时会崩溃,我知道它与方法中的指针有关,但我不知道代码中的什么地方(行号)以及为什么会发生这种情况

我习惯于使用Java等高级语言,我习惯于通过在方法中的某些位置放置打印语法来解决问题,只是为了揭示它崩溃的地方。 我想我可以用c和指针做同样的事情,因为据我所知,代码是从上到下读取的,即1、2、3、4等等。(可能是中断处理程序的另一种行为方式?)

因此,在这个名为delete的函数中,到目前为止,我将printf()放在delete函数的最开头,但程序还是崩溃了

那么我的问题是——是否真的有可能是delete函数中的某些语法(例如,当我循环指针时)在printf()未打印时导致崩溃?

当我认为程序是从下到下执行的,即1、2、3….时,我错了吗

您可以在delete函数的开头使用我的printf函数

顺便问一下,当我从windows收到这个神秘的崩溃消息时,我如何解决这个问题?查看位图

伟大的答案

 int delete(int data) {
            printf("IN THE BEGINNING OF DELETE!!!");
    int result = 0;
    if (queueref.last != NULL) { 

        node *curr_ptr;
        node *prev_ptr;
        node *temp_ptr;

        if (queueref.first->data == data) { 
            temp_ptr = queueref.first;
            queueref.first = queueref.first->next;
            destroy_node(temp_ptr);
            result = 1;
            if (queueref.first == NULL) {
                queueref.last = NULL;
                puts("queue is now empty!!!");
            }
        } else { 
            prev_ptr = queueref.first;
            curr_ptr = queueref.first->next;
            printf("prev_ptr: %d\n", prev_ptr);
            printf("curr_ptr: %d\n", curr_ptr);

            while(curr_ptr != NULL) {
                if (curr_ptr->data == data) {
                    result = 1;
                    if (curr_ptr->next != NULL) { 
                        temp_ptr = curr_ptr;
                        destroy_node(temp_ptr);
                        prev_ptr->next = curr_ptr->next;
                    } else {
                        temp_ptr = curr_ptr;
                        queueref.last = prev_ptr;
                        prev_ptr->next = NULL;
                        destroy_node(temp_ptr);
                    }
                }
                curr_ptr = curr_ptr->next; 
                prev_ptr = prev_ptr->next;
            }
        }
    }
    return result;
}

常见错误,交易如下。这个

        printf("IN THE BEGINNING OF DELETE!!!");
需要

        printf("IN THE BEGINNING OF DELETE!!!\n");
                                             ^^ note the newline

原因是stdio在看到换行符之前不会刷新stdout。如果添加该换行符,则当代码进入函数时,应该会看到printf。如果没有它,程序可能会崩溃,标准输出缓冲区不会被刷新,也看不到printf。

常见错误,这里是交易。这个

        printf("IN THE BEGINNING OF DELETE!!!");
需要

        printf("IN THE BEGINNING OF DELETE!!!\n");
                                             ^^ note the newline

原因是stdio在看到换行符之前不会刷新stdout。如果添加该换行符,则当代码进入函数时,应该会看到printf。如果没有它,程序可能会崩溃,标准输出缓冲区不会被刷新,也看不到printf。

常见错误,这里是交易。这个

        printf("IN THE BEGINNING OF DELETE!!!");
需要

        printf("IN THE BEGINNING OF DELETE!!!\n");
                                             ^^ note the newline

原因是stdio在看到换行符之前不会刷新stdout。如果添加该换行符,则当代码进入函数时,应该会看到printf。如果没有它,程序可能会崩溃,标准输出缓冲区不会被刷新,也看不到printf。

常见错误,这里是交易。这个

        printf("IN THE BEGINNING OF DELETE!!!");
需要

        printf("IN THE BEGINNING OF DELETE!!!\n");
                                             ^^ note the newline

原因是stdio在看到换行符之前不会刷新stdout。如果添加该换行符,则当代码进入函数时,应该会看到printf。如果没有它,程序可能会崩溃,标准输出缓冲区不会被刷新,也不会看到printf。

您的代码似乎有很多实现缺陷。作为一般建议,我建议使用一些经过良好测试的标准队列支持库和静态代码分析器(在这种情况下,我想您甚至会发现动态分析器valgrind非常有用)

例如,如果销毁节点(ptr)的实现相当于免费(ptr),那么您的代码就会在该代码段中引用已销毁的数据(或者换句话说,垃圾):

        while(curr_ptr != NULL) {
            if (curr_ptr->data == data) {
                result = 1;
                if (curr_ptr->next != NULL) { 
                    temp_ptr = curr_ptr;
                    destroy_node(temp_ptr);
                    prev_ptr->next = curr_ptr->next; //<- curr_ptr is still in stack 
                                                     //or register, but curr->next 
                                                     //is garbage 

                    // what if curr_ptr is first node? did you forget to update queueref.first?
                } else {
                    temp_ptr = curr_ptr;
                    queueref.last = prev_ptr;
                    prev_ptr->next = NULL;
                    destroy_node(temp_ptr);
                }
                // if you you need to destroy only one node - you can leave the loop here with break;
            }
            curr_ptr = curr_ptr->next;   /// assigning garbage again if node is found 
            prev_ptr = prev_ptr->next;
while(curr\u ptr!=NULL){
如果(当前->数据==数据){
结果=1;
如果(curr_ptr->next!=NULL){
温度=电流;
销毁节点(临时ptr);
上一页->下一页=当前页->下一页;//下一页
//垃圾
//如果curr_ptr是第一个节点怎么办?您是否忘记先更新queueref.first?
}否则{
温度=电流;
queueref.last=上一个ptr;
prev_ptr->next=NULL;
销毁节点(临时ptr);
}
//如果你只需要摧毁一个节点,你可以用break离开这个循环;
}
curr\u ptr=curr\u ptr->next;///如果找到节点,则再次分配垃圾
上一页=上一页->下一页;
在*大多数*(如果我可以说,基本上这是不可预测的)情况下,使用已销毁数据可以工作的原因是,该内存可被程序的其他部分用于动态分配数据的机会可能因时间和代码流而异

PS


关于Windows机箱中的神秘消息-当程序崩溃时,操作系统基本上生成crashdump并打印寄存器(并转储一些相关内存部分).寄存器和内存转储可以显示崩溃和即时寄存器/堆栈值的位置,但您现在必须对内存映射和汇编程序输出进行理解。可以将崩溃转储加载到调试器(WinDbg)与未压缩的二进制文件一起检查崩溃时的stactrace和局部变量的值。我非常简要地描述了所有这些,您可以找到大量搜索“windows崩溃或崩溃转储分析”的书籍/指南

您的代码似乎有很多实现缺陷。作为一般建议,我建议您使用一些经过良好测试的标准队列支持库和静态代码分析器(我想,在这种情况下,您甚至会发现DynamicAnalyzer valgrind非常有帮助)

例如,如果销毁节点(ptr)的实现相当于免费(ptr),那么您的代码就会在该代码段中引用已销毁的数据(或者换句话说,垃圾):

        while(curr_ptr != NULL) {
            if (curr_ptr->data == data) {
                result = 1;
                if (curr_ptr->next != NULL) { 
                    temp_ptr = curr_ptr;
                    destroy_node(temp_ptr);
                    prev_ptr->next = curr_ptr->next; //<- curr_ptr is still in stack 
                                                     //or register, but curr->next 
                                                     //is garbage 

                    // what if curr_ptr is first node? did you forget to update queueref.first?
                } else {
                    temp_ptr = curr_ptr;
                    queueref.last = prev_ptr;
                    prev_ptr->next = NULL;
                    destroy_node(temp_ptr);
                }
                // if you you need to destroy only one node - you can leave the loop here with break;
            }
            curr_ptr = curr_ptr->next;   /// assigning garbage again if node is found 
            prev_ptr = prev_ptr->next;
while(curr\u ptr!=NULL){
如果(当前->数据==数据){