在Eclipse中进行C编程时的怪异行为

Mahesha999

我已经很长时间没有碰过C了。我的第一语言是C。但是后来(在大学时代)我们被教过C ++,Java和C#。现在我的工作主要涉及Java和groovy。突然之间,我不得不再次执行C。我不熟悉行业如何使用C,因为我从未在项目中使用C做过事。

我从Eclipse CDT开始,在Windows 10上使用MinGW。我的新程序迅速发展壮大。而我的经验不足对我来说却是隐秘的。运行时,我的程序经常崩溃,并显示Windows对话框,提示“ MyProgram.exe已停止工作”。现在我不知道出了什么问题。编译是干净的,没有错误,但是只有一个警告。现在,从Java世界开始,我就像警告不是致命的。所以我只是忽略了它(那就是我缺乏C经验)。并继续进行调试,找到了原因。意识到警告确实与原因有关。在调试中浪费时间造成精神挫败。

所以这是我原始代码中的代码复制问题:

1    #include "stdio.h"
2    #include "limits.h"
3    
4    typedef struct TempStruct TempStruct;
5    
6    struct TempStruct
7    {
8        int a;
9        TempStruct *next;
10    };
11    
12    int function1(TempStruct *param)
13    {
14        return param == NULL;
15    }
16    
17    int function2(TempStruct **param)
18    {
19        if(function1(param))
20        {
21            return INT_MIN;
22        }
23        *param = (*param)->next;
24        return 0;
25    }
26    
27    int main()
28    {
29        TempStruct *tempStructObj = NULL;
30        function2(&tempStructObj);
31        printf("Does not reach here!!!");
32        return 0;
33    }

我的C-noob眼睛没有发现任何错误。很好,我知道该怎么做调试。我在调试中得到了以下结果:

在此处输入图片说明

In main() this is done: *tempStructObj = NULL. So, I was expecting function1() to return 1, making function2() returning from line 21. The issue was that function1() takes TempStruct*. But on line 19, I passed it **param. So inside function1(), param wasnt NULL. So it returned false (0 I guess). So function2() did not returned from line 21. It executed (*param)->next and hence the program crashed.

My questions:

  • Q1. Shouldn't be such issue be reported as Error's instead of Warnings? Is there any setting which can report such potentially fatal warnings to error?
  • Q2. Does eclipse logs the reasons of such sudden app crash somewhere? So instead of debugging by stepping through each line, I can simply refer to the report which can possibly specify the line number which caused the crash
  • Q3. What is industry-standard approach to deal with such mistakes? Of course one will say dont commit the mistake. But I am asking about precautions that are taken to avoid such mistakes or auto detect them. Like above I asked about settings to make eclipse report the issue as fatal one or making crashes to generate report so that stuff can be fixed quickly instead of hours long debuggins. Do you use any better (and possibly involving smaller learning curve) alternative to (eclipse CDT + MinGW + Windows) that will provide more powerful debugging so that I can avoid such errors.
  • Q4. In point 1 of above diagram, what is that Error: Multiple errors reported.... This stuff occurred occasionally, but not always, say once in 5 debugging sessions. What can be the reason behind such ad hoc behavior?
  • Q5. In point 3 of above diagram, what is that (0x62ff2c) value of param inside function1()? If I keep signature of function1() correctly as int function1(TempStruct **param) and change inside reference correctly to *param, *param is correctly 0x0 (i.e. NULL): 在此处输入图片说明

    Edit

    1. This on Ideone works (with C) & prints "Does not reach here!!!". So dont know how it handled (*param)->next.
    2. This on ideone (with C99 Strict) does gives error (not warning).
ljrk

Q1. No, they are warnings as they are legit C code. It could be possible that you want such code. You can use -Werror on gcc to make warnings to errors. Also add some other flags for turning on more warnings like -Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare etc. This'd be a bit closer to what you're probably used to when using Java ;-)

Q2. Atleast on Linux you have coredumps, iirc Windows was minidumps. These can be loaded together with the corresponding executable into a debugger. Then you can access backtraces, values etc.

Q3.

Like above I asked about settings to make eclipse report the issue as fatal one or making crashes to generate report so that stuff can be fixed quickly instead of hours long debuggins.

Log yourself. Also there can be macros for easing this.

Do you use any better (and possibly involving smaller learning curve) alternative to (eclipse CDT + MinGW + Windows) that will provide more powerful debugging so that I can avoid such errors.

IDE is pretty irrelevant for C imho. Use Linux with native GCC instead, MinGW is nice but it can be daunting (my experience). Ofcourse MS VSC++ can also compile C but its just for C++ compatible thus not really specific to one standard.

Q4. Well, multiple errors occured which are listed. If it's difficult to reproduce it might be a problem in your setup, this is exactly the experience I had with MinGW on Windows.

Q5. It's the address -- you have a pointer to a pointer, so the first ("outer") pointer is that address, pointing to another pointer which is NULL. Or more verbosely: tempStructObj is a pointer to NULL (ie. an int_ptr which holds the value 0x0.

To function2 you pass another int_ptr which holds the semi-random value/address of the automatic variable int_ptr tempStructObj is stored Ie. you have such:

Address &tempStructObj: tempStructObj

in the RAM. When you then call function1, you pass the value of this (not-NULL) pointer. Of course the comparison is thus always false. You'd need to compare *param with NULL.

Even more: If you compile with GCC (on Linux) and use really verbose flags you get:

gcc -std=c99 -Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare -o main main.c
main.c: In function ‘function2’:
main.c:19:18: warning: passing argument 1 of ‘function1’ from incompatible pointer type [-Wincompatible-pointer-types]
     if(function1(param))
                  ^
main.c:12:5: note: expected ‘TempStruct * {aka struct TempStruct *}’ but argument is of type ‘TempStruct ** {aka struct TempStruct **}’
 int function1(TempStruct *param)
     ^

So exactly the problem you had ^^

另外,我将function1完全删除它,这完全没有必要,只是混淆了代码。另外,我会为struct和分别使用不同的名称,并在typedef后面附加一个_t另外,我会将其移动到较短的代码段中。附带说明:\nprintf()-call中添加a

修改后的代码:

#include <stdio.h>
#include <limits.h>

typedef struct TempStruct_s {
    int a;
    struct TempStruct_s *next;
} TempStruct_t;

int function(TempStruct_t **param)
{
    if(!*param) {
        return INT_MIN;
    }
    *param = (*param)->next;
    return 0;
}

int main()
{
    TempStruct_t *tempStructObj = NULL;
    function(&tempStructObj);
    printf("Does not reach here!!!\n");
    return 0;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章