【问题标题】:Weird behavior while doing C programming in eclipse [closed]在eclipse中进行C编程时的奇怪行为[关闭]
【发布时间】:2016-07-14 04:53:57
【问题描述】:

我已经很久没有碰过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 眼睛没有发现任何问题。很好,我知道如何进行调试。我在调试中得到了以下结果:

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

我的问题:

  • Q1. 这样的问题不应该报告为错误而不是警告吗?是否有任何设置可以将此类潜在的致命警告报告为错误?
  • Q2. eclipse 会在某处记录这种突然的应用程序崩溃的原因吗?因此,无需逐行调试,我可以简单地参考报告,该报告可能会指定导致崩溃的行号
  • Q3. 处理此类错误的行业标准方法是什么?当然有人会说不要犯错误。但我问的是为避免此类错误或自动检测它们而采取的预防措施。像上面一样,我询问了有关使 eclipse 将问题报告为致命问题或使崩溃生成报告的设置,以便可以快速修复问题,而不是数小时的调试。您是否使用(eclipse CDT + MinGW + Windows)更好的(并且可能涉及更小的学习曲线)替代方案来提供更强大的调试,以便我可以避免此类错误。
  • Q4. 在上图的第 1 点中,Error: Multiple errors reported... 是什么。这种事情偶尔会发生,但并非总是如此,比如在 5 个调试会话中发生一次。这种临时行为背后的原因是什么?
  • Q5. 在上图的第 3 点中,paramfunction1() 中的 (0x62ff2c) 值是多少?如果我将function1() 的签名正确地保留为int function1(TempStruct **param) 并将内部引用正确更改为*param,则*param 是正确的0x0(即NULL):

    编辑

    1. This 在 Ideone 上工作(使用 C)并打印“不到达这里!!!”。所以不知道怎么处理(*param)->next
    2. ideone 上的This(使用 C99 Strict)确实会给出错误(不是警告)。

【问题讨论】:

  • 看起来您使用的是 c,但不是 c++。为什么要添加 c++ 标签?
  • 哦,删除了c++标签。
  • 花了很多精力进行调试,然后写了一个问题和一个关闭请求,但没有评论我做错了什么,值得关闭...:\
  • 只写function2(tempStructObj),对于Q1,你需要找到像-wall这样的编译器标志,它可以启用最高级别的警告,对于Q5,它是指向param的指针,它本身就是一个指针。参数的为NULL,但它的地址为0x62ff2c。
  • 您一次只能提出一个明确的、与主题相关的问题。见How to Ask

标签: c eclipse pointers eclipse-cdt


【解决方案1】:

当你

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

您将变量tempStructObj (0x62ff2c) 的地址发送到function2。做的时候

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

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

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

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

【讨论】:

    【解决方案2】:

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

    第二季度。至少在 Linux 上你有 coredumps,iirc Windows 是 minidumps。这些可以与相应的可执行文件一起加载到调试器中。然后您可以访问回溯、值等。

    第三季度。

    如上所述,我询问了有关使 eclipse 将问题报告为致命问题或使崩溃以生成报告的设置,以便可以快速修复问题而不是长达数小时的调试。

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

    您是否使用任何更好的(并且可能涉及更小的学习曲线)替代 (eclipse CDT + MinGW + Windows) 将提供更强大的调试,以便我可以避免此类错误。

    IDE 与 C imho 无关。使用带有本地 GCC 的 Linux,MinGW 很好,但它可能令人生畏(我的经验)。 当然 MS VSC++ 也可以编译 C,但它只是为了与 C++ 兼容,因此并不真正特定于一个标准。

    第四季度。好吧,列出了多个错误。如果难以重现,可能是您的设置存在问题,这正是我在 Windows 上使用 MinGW 的经验。

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

    function2 传递另一个int_ptr,它保存了自动变量int_ptr tempStructObj 的半随机值/地址 IE。你有这样的:

    地址&tempStructObjtempStructObj

    在内存中。 然后当你调用function1 时,你传递了这个(不是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;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-06
      • 2016-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多