21

我刚刚开始在 C++ 中尝试使用 SDL,我认为定期检查内存泄漏可能是早期形成的一个好习惯。

考虑到这一点,我一直在通过 Valgrind 运行我的“Hello world”程序以捕获任何泄漏,尽管我已经删除了除了最基本的SDL_Init()SDL_Quit()语句之外的所有内容,但 Valgrind 仍然报告丢失了 120 个字节并且仍然可以访问 77k。

我的问题是:内存泄漏是否存在可接受的限制,或者我应该努力使我的所有代码完全无泄漏?

4

11 回答 11

18

请注意,Valgrind 不会在其测量中发现误报。

许多内存分析器的幼稚实现将丢失的内存标记为泄漏,而实际上并非如此。

Maybe have a read of some of the papers in the external links section of the Wikipedia article on Purify. I know that the documentation that comes with Purify describes several scenarios where you get false positives when trying to detect memory leaks and then goes on to describe the techniques Purify uses to get around the issues.

BTW I'm not affiliated with IBM in any way. I've just used Purify extensively and will vouch for its effectiveness.

Edit: Here's an excellent introductory article covering memory monitoring. It's Purify specific but the discussion on types of memory errors is very interesting.

HTH.

cheers,

Rob

于 2008-10-24T12:32:31.237 回答
12

You have to be careful with the definition of "memory leak". Something which is allocated once on first use, and freed on program exit, will sometimes be shown up by a leak-detector, because it started counting before that first use. But it's not a leak (although it may be bad design, since it may be some kind of global).

To see whether a given chunk of code leaks, you might reasonably run it once, then clear the leak-detector, then run it again (this of course requires programmatic control of the leak detector). Things which "leak" once per run of the program usually don't matter. Things which "leak" every time they're executed usually do matter eventually.

I've rarely found it too difficult to hit zero on this metric, which is equivalent to observing creeping memory usage as opposed to lost blocks. I had one library where it got so fiddly, with caches and UI furniture and whatnot, that I just ran my test suite three times over, and ignored any "leaks" which didn't occur in multiples of three blocks. I still caught all or almost all the real leaks, and analysed the tricky reports once I'd got the low-hanging fruit out of the way. Of course the weaknesses of using the test suite for this purpose are (1) you can only use the parts of it that don't require a new process, and (2) most of the leaks you find are the fault of the test code, not the library code...

于 2008-10-24T12:46:33.953 回答
11

Living with memory leaks (and other careless issues) is, at its best, (in my opinion) very bad programming. At its worst it makes software unusable.

You should avoid introducing them in the first place and run the tools you and others have mentioned to try to detect them.

Avoid sloppy programming - there are enough bad programmers out there already - the world doesn't need another one.

EDIT

I agree - many tools can provide false positives.

于 2008-10-24T14:15:03.480 回答
9

如果您真的担心内存泄漏,则需要进行一些计算。

您需要测试您的应用程序一个小时,然后计算泄漏的内存。这样,您将获得泄漏的内存字节/分钟值。

现在,您需要估计程序会话的平均长度。例如,对于 notepad.exe,15 分钟听起来对我来说是一个不错的估计。

如果 (平均会话长度)*(泄漏字节/分钟) > 0.3 * (您的进程通常占用的内存空间),那么您可能应该做更多的努力来减少内存泄漏。我刚刚补了0.3,用常识来确定你可以接受的阈值。

请记住,成为一名程序员的一个重要方面是成为一名软件工程师,而工程通常是关于从两个或多个糟糕的选项中选择最差的选项。当您需要衡量一个选项实际上有多糟糕时,数学总是很方便。

于 2008-10-24T12:25:43.590 回答
8

Most OSes (including Windows) will give back all of a program's allocated memory when the program is unloaded. This includes any memory which the program itself may have lost track of.

Given that, my usual theory is that it's perfectly fine to leak memory during startup, but not OK to do it during runtime.

So really the question isn't if you are leaking any memory, it is if you are continually leaking it during your program's runtime. If you use your program for a while, and no matter what you do it stays at 120 bytes lost rather than increasing, I'd say you have done great. Move on.

于 2008-10-24T14:05:56.447 回答
7

对于桌面应用程序,小的内存泄漏并不是真正的问题。对于服务(服务器),不允许出现内存泄漏。

于 2008-10-24T12:24:38.053 回答
2

这取决于您的应用程序。一些泄漏可能是不可避免的(由于查找泄漏所需的时间与截止日期相比)。只要您的应用程序可以随心所欲地运行,并且在那段时间内不占用大量内存,那可能就可以了。

于 2008-10-24T12:19:52.027 回答
2

It does look like SDL developers don't use Valgrind, but I basically only care about those 120 bytes lost.

With this in mind, I've been running my 'Hello world' programs through Valgrind to catch any leaks, and although I've removed everything except the most basic SDL_Init() and SDL_Quit() statements, Valgrind still reports 120 bytes lost and 77k still reachable.

Well, with Valgrind, "still reachable memory" is often not really leaked memory, especially in such a simple program. I can bet safely that there is basically no allocation in SDL_Quit(), so the "leaks" are just structures allocated once by SDL_Init().

Try adding useful work and seeing if those amounts increase; try making a loop of useful work (like creating and destroying some SDL structure) and see if the amount of leaks grows with the amount of iterations. In the latter case, you should check the stack traces of the leaks and fix them.

Otherwise, those 77k leaks count as "memory which should be freed at program end, but for which they rely on the OS to free it.

So, actually, I'm more worried right now by those 120 bytes, if they are not false positives, and they are usually few. False positives with Valgrind are mostly cases where usage of uninitialized memory is intended (for instance because it is actually padding).

于 2009-01-12T03:50:12.367 回答
1

As per Rob Wells' comments on Purify, download and try out some of the other tools out there. I use BoundsChecker and AQTime, and have seen different false positives in both over the years. Note that the memory leak might also be in a third party component, which you may want to exclude from your analysis. From example, MFC had a number of memory leaks in the first view versions.

IMO, memory leaks should be tracked down for any code that is going into a code base that may have a long life. If you can't track them down, at least make a note that they exist for the next user of the same code.

于 2008-10-24T12:47:43.093 回答
1

Firstable memory leaks are only a serious problem when they grow with time, otherwise the app just looks a little bigger from the outside (obviously there's a limit here too, hence the 'serious'). When you have a leak that grows with time you might be in trouble. How much trouble depends on the circumstances though. If you know where the memory is going and can make sure that you'll always have enough memory to run the program and everything else on that machine you are still somewhat fine. If you don't know where the memory is going however, i wouldn't ship the program and keep digging.

于 2008-10-24T12:56:25.293 回答
1

With SDL on Linux in particular, there seem to be some leaking in the underlying X windows library. There's nothing much you can do about those (unless you want to try to fix the library itself, which is probably not for the faint hearted).

You can use valgrind's suppression mechanism (see --suppressions and --gen-suppressions in the valgrind man page) to tell it not to bother you with these errors.

In general we do have to be a little more lenient with third party libraries; while we should absolutely not accept memory leaks in our own code, and the presence of memory leaks should be a factor when choosing between alternative third party libraries, sometimes there's no choice but to ignore them (though it may be a good idea to report them to the library maintainer).

于 2009-01-22T02:24:51.447 回答