调试c程序

时间:2010-07-15 07:56:11

标签: c debugging

在某种意义上编程很容易。但是bug总是会带来更多麻烦。谁能帮助我在c?

中使用好的调试技巧和软件

11 个答案:

答案 0 :(得分:8)

来自“编程风格的元素” Brian Kernighan,第2版,第2章:

  

每个人都知道调试是两次   和编写程序一样难   第一名。所以,如果你像聪明一样   你可以在写作时,怎么会   你有没有调试过它?

从那以后;不要“太聪明”!

但除此之外,已经给出了答案;使用调试器!这是工具方面的起点。你会惊讶于有多少程序员在没有调试器的帮助下挣扎,他们这样做是愚蠢的。

但是在你进入调试器之前,让你的编译器尽可能地帮助你;将警告级别设置为高,并将警告设置为错误。诸如lint,pclint或QA-C之类的静态分析工具会更好。

答案 1 :(得分:4)

用于调试的工具都很好,对于某些类型的错误,他们只会直接指出问题所在。我调试的最佳提示是你需要以正确的方式思考它。对我有用的是:

  • 编译器可能没有损坏。我已经和C一起工作了25年,而且在那段时间里,我几乎总是出错。
  • 阅读错误消息。我经常回顾一下错误信息,事后才意识到它确实告诉了我到底出了什么问题。
  • 阅读文档。确保您没有对不正确的语言或库做出假设。
  • 制作问题的心理模型。我问自己在我的代码中需要做些什么才能实现我看到的结果。然后添加调试语句,断言或者只是在调试器中逐步执行(如果可以的话)以查看实际发生的情况。
  • 与其他人讨论此问题。只是向第三方描述它通常会导致对可能发生的事情的启示。

其他人会有其他方法来接近调试,但我发现你是否有一个结构化的方法,而不是随意改变你的东西,你通常会到那里,当你为不可避免的事做好准备为什么没有我马上就看到了

答案 2 :(得分:3)

C的最佳调试器

  1. GDB
  2. 内存泄漏检查的最佳工具:

    1. Valgrind的

答案 3 :(得分:2)

以下是流行的调试工具。

一些非常简单技巧/建议

- >请务必检查您的代码中是否已取消引用wild/dangling pointer

示例1)

int main()
{
     int *p;
     *p=10; //Undefined Behaviour (crash on most implementations)
}

示例2)

int main()
{

     int *p=malloc(sizeof(int));
     //do something with p

     free p;
     printf("%d", *p); ////Undefined Behaviour (crash on most implementations)
}

- >始终在使用

之前初始化变量
 int main()
  {

    int k;

    for(int i= k;i<10;++i)
              ^^
            Ouch
      printf("%d",i");
  }

答案 4 :(得分:1)

单元测试。使您的软件更容易正确。

答案 5 :(得分:1)

  1. gdb是一个分析程序的调试器。
  2. 其他技术是使用printf或logs
  3. Valgrind提供可执行文件的动态分析
  4. Purify提供静态和动态分析。 Sparrow和Prevent是其他一些与Purify竞争的工具。

答案 6 :(得分:1)

这可以分为:

预防措施:

  1. 使用严格的编码风格,不要弄得一团糟
  2. 使用注释和代码修订
  3. 使用静态代码分析工具
  4. 尽可能使用断言
  5. 不要过于复杂
  6. 后呈文

    1. 使用调试器/跟踪器
    2. 使用内存检查工具
    3. 使用回归测试
    4. 使用你的大脑

答案 7 :(得分:1)

除了所有其他建议(gdb,valgrind,所有这些)之外,编写代码时的一些简单规则在以后进行调试时会有很大帮助。

  • 始终使用正确的类型 语义。无符号类型(最好的 size_t)表示基数的数组索引和数字, ptrdiff_t指针差异, off_t用于标记和案例区别的文件偏移等enum类型。
  • 几乎没有必要 内置类型intlongchar或 随你。尽可能避免使用它们。
  • 特别是请勿使用char 算术,签名问题是一个瘟疫。使用uint8_tint8_t 如果你觉得需要这样的话 的事情。
  • 始终初始化变量,所有变量:整数,double,指针,struct。它是 这不是真的,效率较低 用现代的编译器。在大多数情况下,它只会 在没有必要时被优化掉。 但特别是指针变量 没有正确初始化可以 产生虚假错误并制作代码 很难调试。如果你有它们 已初始化为NULL您的计划 会提前失败,你的调试器会告诉你这个地方。
  • 编译所有警告,和 不要完成你的代码整理,直到 编译器没有给出单个 警告。他们现在相当擅长,利用。
  • 使用不同的优化进行编译 选项,甚至更好 不同版本的编译器, 或完全更好 不同的编译器 平台。
  • 使用assert宏。这迫使你想到你的假设,也会让你的 如果代码未得到满足,代码会提前失败。

答案 8 :(得分:0)

离开我的头顶,Valgrind。

答案 9 :(得分:0)

您可能还希望通过阅读本书Debugging by David Agans来提高您的调试技巧。每个程序员都应该在他们职业生涯的早期阅读。

答案 10 :(得分:0)

如果你使用linux,那么valgrind会遇到内存问题。在linux上也使用gdb / ddd。在Windows上,许多Windows程序员似乎并不了解windbg。它非常有用,但有像gdb这样的学习曲线;比visual studio中的内置调试器更强大。学习使用assert,你会捕获很多东西,你可以在发布代码中关闭它,如果你愿意的话。使用Check,cunit等单元测试框架。始终初始化指针,如果没有别的话,为NULL。释放指针时,将其设置为NULL。比你的用户更好地捕获段错误。选择一个编码标准并坚持下去,一致性将帮助您减少错误。如果可能的话,保持你的功能小,这将使你不会有10级深度支撑,这是逻辑梦魇。如果使用gcc进行编译,请使用-Wall和-Wextra。使用strn *函数代替str *函数。非常值得他们强迫你做的额外思考。