如何学习C调试和最佳实践

dav*_*off 7 c apache debugging gdb valgrind

我在C中编写了一个Apache模块.在某些情况下,我可以将它转换为段错误,但我不知道为什么.此时,它可能是我的代码,它可能是我编译程序的方式,或者它可能是OS库中的错误(在调用dlopen()期间发生了段错误).

我尝试过运行GDB和Valgrind但没有成功.GDB让我对dlopen()系统调用进行了回溯,看起来毫无意义.在Valgrind中,这个bug实际上似乎消失了,或者至少变得不可重复.另一方面,对于这些工具,我完全是新手.

我对生产质量的C编程有点新兴(我多年前从C开始,但从未专业地使用它.)对于我学习调试程序的最佳方法是什么?我应该调查哪些其他工具?总之,您如何弄清楚如何应对新的bug挑战?

编辑:只是为了澄清,我想感谢Sydius和dmckee的输入.我看了一下Apache的指南,并且对dlopen(以及dlsym和dlclose)非常熟悉.我的模块大部分都工作(大约有3k行代码,只要我没有激活这一段,事情就好了.)

我想这是我原来的问题所在 - 我不知道接下来该做什么.我知道我没有充分发挥GDB和Valgrind的潜力.我知道我可能没有用正确的标志进行编译.但是我很难搞清楚.我可以找到初学者的指南,告诉我我已经知道的东西,以及告诉我超过我需要了解但没有指导的人工页面.

Nor*_*sey 5

不幸的是,GNU工具并不是最好的,我的经验是动态链接器极大地混淆了水域.如果您可以让Apache静态链接到您的模块,这将使gdb尤其能够更可靠地执行.我不知道这有多容易; 很大程度上取决于Apache构建系统.

令人担忧的是,你不能轻易地用valgrind重现这个bug,这并不令人震惊.

关于使用正确的标志进行编译,如果您编译所有内容,valgrind和gdb都会为您提供更好的信息-g -O0.不要相信gcc手册页上的说法gcc -g -O足够好; 它不是---甚至-O会导致优化器消除源代码中的变量.


dmc*_*kee 2

非常一般的建议:

  • 再看看那个回溯。您控制的代码中是否有任何堆栈帧?如果是这样,那条线是什么,那里发生了什么?

  • 你知道有什么dlopen()作用吗?如果没有阅读手册。如果回溯不包含您的任何代码,则在Apache尝试加载您的代码时很可能会失败。您确定已经使用正确的编译器选项构建了模块吗?

  • 有效的调试需要了解您的环境和工具。Sydius 的建议在这里很好。

  • 如果您陷入其他路径,请检查您是否可以编写、加载和运行一个简单的模块。您可能会在几乎所有有关该主题的文档中找到这样的示例。


戴夫澄清:初学者和专家之间可能是一个棘手的问题。

您是否在其他地方不使用的违规代码中调用库?也许该资源的加载路径就被搞乱了。

除此之外我几乎没有什么建议了。对不起。


注意:去年我有机会读了 David J. Agans 的书《调试》 。它不是特定于软件的,但是值得一读,即使您已经是一个非常好的调试器,它也会很有帮助。