代码之家  ›  专栏  ›  技术社区  ›  David Johnstone

Java和C语言中的内存管理有什么不同?

  •  4
  • David Johnstone  · 技术社区  · 15 年前

    我在看书呢 2010 CWE/SANS Top 25 Most Dangerous Programming Errors 其中一个条目是 Buffer Copy without Checking Size of Input . 它建议使用具有功能的语言来防止或缓解此问题,并说:

    例如,许多语言 执行自己的内存管理, 如Java和Perl,不是主题。 以缓冲溢出。其他语言, 如ADA和C,通常提供 溢出保护,但是 保护可以被禁用 程序员。

    我没有意识到Java和C语言在内存管理方面有任何不同的方式。Java是如何不受缓冲区溢出的影响的,而C?如何在C中禁用此保护?

    2 回复  |  直到 13 年前
        1
  •  5
  •   Mitch Wheat    15 年前

    Java不支持原始指针(严格地说,它不支持指针运算)。

    在C中,您可以使用 unsafe code and pointers 和非托管内存,这使得缓冲区溢出成为可能。见 unsafe 关键字。

    为了维护类型安全, C不支持指针 默认情况下为算术。然而,通过 使用不安全的关键字,您可以 定义一个不安全的上下文,其中 可以使用指针。为了更多 有关指针的信息,请参见 话题 Pointer types .

        2
  •  4
  •   Zack Jannsen    13 年前

    好答案。我想补充说,Java依赖于堆栈或堆内存位置的使用。C也是。使用原始指针的想法是对C的一个补充,它来自于C代码背景。C语言和C/C++虽然不是相同的代码语言,但它们确实有一些共同的语义。使用“不安全”代码的想法允许您避免将大对象放在堆上,在内存中,每个运行时实例的内存限制在2GB左右(对于每个JVM实例来说,对于每一个CLR来说都是C),而不会因为垃圾收集而引起戏剧性的性能下降。在某些情况下,您可以使用C的能力来利用不安全或手动管理的内存指针来绕过这样一个事实:对于堆外的缓存等问题,没有足够多的第三方工具。

    我会提醒你,如果你使用不安全的代码,一定要熟悉“一次性类型”和“终结器”。这可能是一个相当高级的实践,不正确地处理对象的后果与C代码相同…可怕的记忆泄漏。影响是你的应用程序内存不足,它会崩溃(不是很好)。这就是为什么C在默认情况下不允许使用它,并且您需要用“unsafe”关键字覆盖手动控制指针的任何用法。这可以确保任何手动处理的内存都是有意的。在处理“unsafe”关键字时戴上C代码帽。

    在安德鲁·特洛尔森的《Pro C 2010和.NET平台》中的“了解对象生命周期”一章中,有一个很好的参考。如果您喜欢在线参考,请访问msdn网站 Implementing Finalize and Dispose to Clean Up Unmanaged Resources

    最后一个注意事项-非托管内存释放在对象的终结器部分(~objectname()…)。这些模式确实会增加性能开销,因此,如果您处理的是较低的延迟场景,那么最好是保持对象较轻。如果你处理的是人类的反应,那么在绝对必要的情况下,你可以考虑这一点。