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

Weird behavior while doing C programming in eclipse

好久好久没碰C了。我的第一语言是 C。但后来我们学习了 C++、Java 和 C#(在大学时代)。现在我的大部分工作涉及 Java 和 groovy。突然间我不得不再次做C。我不熟悉行业如何使用 C,因为我从来没有在项目中用 C 做事。

我从 eclipse CDT 开始,在 Windows 10 上使用 MinGW。我的新程序发展很快。我缺乏经验并没有透露给我。当我 运行 时,我的程序曾经崩溃,显示 Windows 对话框说 "MyProgram.exe has stopped working"。现在我不知道出了什么问题。编译很干净,没有错误,但只有一个警告。现在从 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菜鸟眼睛没看出有什么不对的地方。很好,我知道如何进行调试。我在调试中得到以下信息:

main() 中完成:*tempStructObj = NULL。所以,我期待 function1() 到 return 1,从第 21 行开始 function2() returning。 问题是 function1() 需要 TempStruct*。但是在第19行,我通过了**param。所以在 function1() 里面,param 不是 NULL。所以它 returned false0 我猜)。所以 function2() 没有从第 21 行开始 return。它执行了 (*param)->next,因此程序崩溃了。

我的问题:

当你

TempStruct *tempStructObj = NULL;
function2(&tempStructObj);

您正在向 function2 发送变量 tempStructObj (0x62ff2c) 的地址。当做

if(function1(param)){
    return INT_MIN;
}

您正在发送相同的地址 (0x62ff2c)。因此,param == NULLfalse

问题 5:如果按照您的建议使用正确的签名,那么您会检查 tempStructObj 指向的值,这是您想要的,并且一切正常。

你得到的关于无法访问内存 0x4 的错误是由于你的结构和错误的空检查。 (*param)->next 预期在具有 int 和另一个指针的内存区域上工作。但是,*param 指向地址 0x0,因此 int 位于地址 0x0,而 next 指针位于地址 0x4,因此出现错误。

Q1。不,它们是警告,因为它们是合法的 C 代码。 可能您需要这样的代码。您可以在 gcc 上使用 -Werror 来对错误发出警告。还要添加一些其他标志以打开更多警告,例如 -Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare 等。这会更接近您在使用 Java 时可能习惯的内容;-)

Q2。至少在 Linux 上你有核心转储,iirc Windows 是小型转储。这些可以与相应的可执行文件一起加载到调试器中。然后你可以访问回溯、值等。

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.

自己登录。也可以有宏来缓解这个问题。

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 与 C imho 无关。将 Linux 与本机 GCC 结合使用,MinGW 很不错,但它可能令人生畏(我的经验)。 当然 MS VSC++ 也可以编译 C,但它只是为了 C++ 兼容,因此并不特定于某一标准。

Q4。好吧,列出了多个错误。如果难以重现,则可能是您的设置有问题,这正是我在 Windows.

上使用 MinGW 的经历

Q5。它是地址——你有一个指向指针的指针,所以第一个 ("outer") 指针就是那个地址,指向另一个指针 NULL。 或者更详细地说: tempStructObj 是指向 NULL 的指针(即 int_ptr 保存值 0x0

你传给function2另一个int_ptr里面保存了自动变量int_ptr tempStructObj的半随机value/address IE。你有这样的:

地址&tempStructObjtempStructObj

在内存中。 当您随后调用 function1 时,您将传递此 (not-NULL) 指针的值。当然,这种比较总是错误的。 你需要比较 *paramNULL.

更多: 如果您使用 GCC(在 Linux 上)编译并使用非常冗长的标志,您会得到:

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)
     ^

这正是你遇到的问题^^

另外,我会完全删除 function1,这是完全没有必要的,只会混淆代码。此外,我会为 structtypedef 使用不同的名称,并在后者后面附加一个 _t。另外,我会将它移到一段较短的代码中。 附带说明:在 printf()-call.

中添加一个 \n

编辑代码:

#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;
}