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

发布于 2024-07-09 13:50:45 字数 1454 浏览 10 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

在梵高的星空下 2024-07-16 13:50:45

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

无法使用 valgrind 轻松重现该错误,这令人担忧,但并不令人震惊。

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

Unfortunately the GNU tools are not the best, and my experience is that the dynamic linker muddies the waters enormously. If you can get Apache to link statically with your module that will enable gdb especially to perform more reliably. I don't know how easy that is; a lot depends on the Apache build system.

It's worrisome but not shocking that you can't easily reproduce the bug with valgrind.

Regarding compiling with the right flags, both valgrind and gdb will give you much better information if you compile everything in sight with -g -O0. Don't believe the claims on the gcc man page that gcc -g -O is good enough; it isn't---even -O will cause variables in the source code to be eliminated by the optimizer.

合久必婚 2024-07-16 13:50:45

我确信调试技术在一般语言中是独立的,并且不存在“C 调试”这样的想法。
有很多不同的工具可以帮助您发现简单的问题,例如内存泄漏,或者只是代码中的愚蠢错误,有时它甚至可以捕获简单的内存溢出。
但对于真正难以发现的问题,例如源自多任务/中断的问题、DMA 内存损坏,唯一的工具是您的大脑和编写良好的代码(提前考虑该代码将被调试)。 您可以找到有关准备代码以调试的更多信息 此处。 从Sydius帖子看来,Apache已经有一个良好的跟踪机制到位,因此只需使用它并将类似的内容添加到您的代码库中即可。
另外,我想说调试的另一个重要步骤是“不要假设/思考”。 你的所有步骤都基于赤裸裸的事实,在基于该假设采取另一步骤之前,以 100% 的准确性证明你的所有假设。 基于假设进行调试通常会给您带来错误的方向。

在戴夫的澄清后进行编辑:

下一步应该找到导致问题的代码的最小部分。 如果您禁用某些部分,则模块会被加载,这让您感到难过。 只要使该部分尽可能小,删除/删除该部分中的所有内容,直到您找到理想的一行,该行将导致模块无法加载。 当你找到这条线之后。 这将是开始使用你的大脑的确切时间:) 只是不要忘记 100% 验证这是线路

I'm sure that debugging techniques are in general language independent and there is no such think "C debugging".
There is a lot of different tool that can help you find simple problems like memory leak, or just stupid mistakes in the code, some times it even can catch simple memory overruns.
But for real hard to find problems like problems originated from multitasking/interrupt, dma memory corruption the only tool is your brain and well written code (with thinking in advance that this code will be debugged). You can find more about preparing your code to debugging here. It seems from Sydius post that Apache already have a good tracing mechanism in place, so just use it and add simalar to your code base.
In additional i would say that another important step in debugging is "don't assume/think". Base all your steps on bare facts, prove all your assumption with 100% accuracy before you making another step based on that assumption. Basing your debugging on assumption usually will bring you to wrong direction.

Edit after Dave's clarification:

You next step should be find the smallest part of the code that cause the problem. You sad that if your disable certain section the module is loaded. just make this section as small is possible, remove/moke everything in the section until you will find ideally one line that will cause the module not to load. And after you find this line. it will be an exact time to start using your brain :) Just don't forget to 100% verify that this is the line.

浪荡不羁 2024-07-16 13:50:45

非常一般的建议:

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

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

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

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


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

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

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


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

Very general advice:

  • Look again at that backtrace. Are any of the stack frames in code you control? If so, what line, and what is happening there?

  • Do you know what dlopen() does? If not read the manual. If the backtrace does not include any of you code, this may well be failing at the time Apache tries to load your code. Are you sure you've built the module with the right compiler options?

  • Effective debugging requires knowing your environment and tools. Sydius's advice is good here.

  • If you're stuck on other paths, check that you can write, load, and run a trivial module. Probably you'll find an example of this in almost any documentation on the subject.


To dave's clarification: Between beginner and expert can be a tough spot.

Are you calling in libraries in the offending code that you don't use elsewhere? Maybe the loader path is messed up just for that resource.

Aside from that I'm just about out of advice. Sorry.


NB: I had occasion to read David J. Agans' book Debugging last year. It is not software specific, but is a good read, and helpful even if you are already a pretty good debugger.

风柔一江水 2024-07-16 13:50:45

事实上,它在 dlopen() 调用上失败的事实对我来说似乎有点可疑。 尝试打开共享对象时,可能会出现很多问题; 但它们都不应该导致段错误。

我能想到的一个例外是 SO 的库初始化中的问题。 在此基础上,我会建议您可以尝试获取更多信息。

  • 检查您的库路径,并确保您尝试加载的库位于此路径中。 (注意:由于您使用的是 Apache,我认为您还需要检查运行 Apache 的用户的库路径。(我认为该用户是“nobody”。)我相信您正在寻找 LD_LIBRARY_PATH 环境变量。)另请注意,如果您有该库的多个版本,这可能非常重要。 确保您加载的是正确版本的库。
  • 作为一般的调试原则,尽量简化问题。 鉴于我对 Apache 模块知之甚少,我会尝试将 Apache 从等式中删除:尝试编写一个简单的 C 程序,其功能只不过是 dlopen() 以及可能的后续 dlsym(),然后退出。 该程序提供了一个更简单的环境来排除故障和/或调试。 如果该程序运行正常,那么您可能需要更仔细地查看程序段故障时的不同之处。 (Apache 的做法有何不同?)另一方面,如果您的程序也出现段错误,您可能会考虑库、程序的编译器切换以及程序中的代码存在潜在问题。 (或以上所有内容。)

虽然我可能没有提供很多通用调试技巧,但我希望这里的一些内容可能会有所帮助。

The fact that it is failing on the dlopen() call seems a bit suspect to me. There are a number of things that can go wrong when attempting to open a shared object; but none of them should cause a seg fault.

The one exception I can think of is a problem in the library initialization of the SO. On that basis, I would suggest a few things you could try to get more information.

  • Check your library path, and ensure that the library you're trying to load is in this path. (Note: Since you're using Apache, I think you also need to check the library path for the user under which Apache is running. (I think the user is "nobody".) I believe you're looking for the LD_LIBRARY_PATH environment variable.) Also note that if you have multiple versions of the library, this can be really important. Make sure you're loading the correct version of the library.
  • As a general debugging principle, try to simplify the problem. Given that I know little about Apache modules, I would try to remove Apache from the equation: Try writing a simple C program that does little more than a dlopen() and possibly the subsequent dlsym(), then exits. This program provides a much simpler environment to troubleshoot and/or debug. If this program runs cleanly, then you may need to look more closely at what's different when the program seg faults. (What's Apache doing differently?) On the other hand, if your program also seg faults, you may consider a potential problem with the library, your compiler switches for the program, and the code in the program. (Or all of the above.)

While I may not have offered very many general purpose debugging tips, I hope something here may have been helpful.

娜些时光,永不杰束 2024-07-16 13:50:45

我查看了 valgrind 文档,默认情况下它不检查子进程。 如果Apache 可以在子线程中运行您的模块,我一点也不感到惊讶。 请尝试

valgrind --trace-children=yes ....

I had a look at the valgrind documentation and by default it doesn't check child processes. It wouldn't surprise me at all if Apache could run your module in a child thread. Please try

valgrind --trace-children=yes ....
静谧 2024-07-16 13:50:45

我推荐我们的非计算机科学学生(即电气工程、数学、物理学生)参加 Kernighan 的编程讲座“编程实践”。 它很好地提供了一些有助于开发的基本概念(例如测试,它来了:调试)。

如果您已经是经验丰富的程序员,那么这对您来说可能太基础了。 那么我再给你一句禅宗谚语:“未经经验过滤的智慧是毫无价值的”。

我只能备份的一个答案:再次查看堆栈跟踪,这是通过调试最相关的帮助(特别是在边界处,执行跨越不同的模块(特别是你的模块和 lib/OS 边界),然后看看函数的参数并检查它们是否正常)。

Our non CS students (i.e. electrical engineering, math, physic students) I recommend in the programming lectures "The Practice of Programming" from Kernighan. It good delivers some basic concepts which aids devlopment (like testing and here it comes: debugging).

If you are already experienced programmer, it is maybe too basic for you. Then I have just one more of this Zen proverbs for you: "Wisdom withouth the filtering through experience is worthless".

One answer I can only back up: Look again at the stack trace, this is the most relevant help by debugging (esp there at the borders, where the execution crosses different modules (esp yours and the lib/OS borders), and look at the argument of the function and check if they are sane).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文