在 gcc 中不启用内存管理
编译时是否有任何选项可以在 gcc 中启用无内存管理?
Is there any option for enabling no memory management in gcc while compiling?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
编译时是否有任何选项可以在 gcc 中启用无内存管理?
Is there any option for enabling no memory management in gcc while compiling?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(2)
在调试使用 GCC 编译的 C 代码时使用 Valgrind 的要点:
使用 -O0 编译代码。在一些相对罕见的情况下(例如内联汇编)您可能需要-O1。 切勿使用更高的优化级别。编译器会严重破坏你的代码,让你的生活变得不可能。变量可以完全消失,函数可以在内联时神秘地消失,循环展开等等。基本上,使用除 -O0 之外的任何内容,您都会面临可执行代码与源代码几乎没有相似之处的风险。
使用 -g GCC 选项将调试符号添加到代码中,并且不要删除可执行文件。与任何其他调试器非常相似,valgrind 将通过可用的调试符号产生无限更有用的输出。它们将帮助 valgrind 将内存地址与代码中的特定文件和行号进行匹配,这是无价的。
要跟踪内存泄漏和许多其他问题,我建议运行您的程序:
然后在 valgrind.log 文件中查找发现的任何问题。
编辑:
关于我建议的 valgrind 选项:
--log-file= 告诉 valgrind 将其输出发送到文件,我相信当您调试输出到控制台的程序时,或者当有发现了很多问题。
--leak-check=full 告诉 valgrind 告诉您有关每个泄漏内存块的详细信息。
--track-origins=yes 告诉 valgrind 找出未初始化值的来源。它与内存泄漏没有任何关系,尽管它可以帮助处理其他问题。不过,它会使您的程序变慢,因此您可能需要删除此选项,并仅在跟踪未初始化值时添加它。
--show-reachable=yes 告诉 valgrind 输出已分配但未释放的内存块,即使在程序退出时仍然有指向它们的指针。从技术上讲,这些块并没有丢失/泄漏,因为您仍然拥有指向它们的指针。尽管如此,它们仍然可以 a) 指示程序中的逻辑问题(例如,无限增长的列表) b) 如果您的 main() 作为函数集成到另一个较大的程序中,它们可以并且将会成为内存泄漏。最好不要留下这样的问题。
有一个 --track-fds=yes 选项可以帮助查找泄漏文件描述符而不仅仅是内存。
一些程序员主张不要在程序结束时释放内存或关闭文件描述符,因为操作系统无论如何都会这样做。虽然那里有性能和代码大小优势,但恕我直言,这只能由经验丰富的程序员来完成,并且应该通过删除生产版本的所述代码来完成,而不是只是从不写它。否则,这会助长不应该允许的不良编码实践。
编辑2:
一个重要的提示:如果 valgrind 指示您的代码中存在问题,那么它很可能是正确的,即使您的程序没有崩溃。一些“小”错误(例如,读取超出缓冲区末尾的一个字节)可能仍然不可见,具体取决于结构对齐、内存分配器行为、平台、编译器版本和标志或月相。如果您更改编译器、libc、平台或位数(例如从 64 位更改为 32 位),存在此类问题的代码可能会中断。
Main points on using Valgrind while debugging C code compiled with GCC:
Compile your code using -O0. In some relatively rare cases (e.g. inline assembly) you may need -O1. Never use higher optimisation levels. The compiler will mangle your code so much that it can make your life impossible. Variables can disappear completely, functions can go mysteriously away as they get inlined, loops become unrolled and so on. Basically with anything other than -O0 you run the risk that the executable code will bear little resemblance to your source code.
Use the -g GCC option to add debugging symbols to your code and DO NOT strip the executables. Much like any other debugger, valgrind will produce infinitely more useful output with debugging symbols available. They will help valgrind match memory addresses to specific files and line numbers in your code which is invaluable.
To track memory leaks and many other problems I suggest running your program with:
Then look in the valgrind.log file for any problems found.
EDIT:
About the valgrind options I suggested:
--log-file= tells valgrind to send its output to a file, which I believe can make things easier when you are debugging programs with output to the console, or when there are lots of issues found.
--leak-check=full tells valgrind to tell you details about each leaked memory block.
--track-origins=yes tells valgrind to find out where uninitialised values came from. It does not have anything to do with memory leaks, although it can help deal with other issues. It makes your program slower, though, so you might want to remove this option and add it only when you are tracking uninitialised values.
--show-reachable=yes tells valgrind to output memory blocks that have been allocated and not freed, even if there are still pointers to them at program exit. These blocks are not technically lost/leaked, since you still have pointers to them. Still, they can a) indicate a logic problem in your program (e.g. a list that grows indefinitely) b) they can and will become memory leaks if your main() becomes integrated as a function in another larger program. It would be best that there are no such issues left.
There is a --track-fds=yes option that can help find leaking file descriptors instead of just memory.
Some programmers advocate against freeing memory or closing file descriptors at program end, since the OS does that anyway. While there is a performance and code size advantage there, IMHO this should only be done by experienced programmers only, and it should be done by removing said code for the production release, rather than just never writing it. Otherwise, this encourages bad coding practices that should not be allowed.
EDIT 2:
One important hint: If valgrind indicates a problem in your code, it is most probably right, even if your program does not crash. Some "minor" errors (e.g. reading one byte past the end of a buffer) can remain unseen, depending on structure alignment, memory allocator behaviour, platform, compiler version and flags, or the phase of the moon. Code with such issues might just break if you change compiler, libc, platform or bitness (e.g. go from 64 to 32 bit).
编译程序时不进行优化,并使用调试符号以获得最佳结果 (
-O0 -g
)。现在运行程序的一个实例,利用尽可能多的功能,像这样包装调用:
我经常发现将以下标志传递给 valgrind 很有用:
但是 valgrind 会提供很多提示来帮助您了解应该传递哪些参数它可以在不太彻底的通道上找到东西。
Compile your program without optimization, and with debug symbols for best results (
-O0 -g
).Now run an instance of your program, utilizing as much functionality as possible, wrapping the call like so:
I often find it useful to pass the following flags to valgrind:
However valgrind will provide much prompting to assist you regarding what parameters to pass, should it find stuff on less thorough passes.