简体   繁体   English

Java和C#中的内存管理有何不同?

[英]How does memory management in Java and C# differ?

I was reading through 2010 CWE/SANS Top 25 Most Dangerous Programming Errors and one of the entries is for Buffer Copy without Checking Size of Input . 我正在阅读2010年CWE / SANS排名前25位最危险的编程错误 ,其中一个条目是缓冲区复制而不检查输入大小 It suggests using a language with features to prevent or mitigate this problem, and says: 它建议使用具有功能的语言来预防或缓解此问题,并说:

For example, many languages that perform their own memory management, such as Java and Perl, are not subject to buffer overflows. 例如,许多执行自己的内存管理的语言(如Java和Perl)不会受到缓冲区溢出的影响。 Other languages, such as Ada and C#, typically provide overflow protection, but the protection can be disabled by the programmer. 其他语言(如Ada和C#)通常提供溢出保护,但程序员可以禁用保护。

I was not aware that Java and C# differed in any meaningful way with regard to memory management. 我不知道Java和C#在内存管理方面有任何有意义的不同。 How is it that Java is not subject to buffer overflows, while C# only protects against overflows? Java如何不受缓冲区溢出的影响,而C#只能防止溢出? And how is it possible to disable this protection in C#? 如何在C#中禁用这种保护?

java does not support raw pointers (strictly speaking it does not support pointer arithmetic). java不支持原始指针(严格来说它不支持指针运算)。

In C#, you can use unsafe code and pointers , and unmanaged memory, which makes buffer overruns possible. 在C#中,您可以使用不安全的代码和指针以及非托管内存,这会使缓冲区溢出成为可能。 See unsafe keyword. 请参阅unsafe关键字。

To maintain type safety and security, C# does not support pointer arithmetic, by default. 为了保持类型安全性和安全性,默认情况下C#不支持指针算法。 However, by using the unsafe keyword, you can define an unsafe context in which pointers can be used. 但是,通过使用unsafe关键字,您可以定义可以使用指针的不安全上下文。 For more information about pointers, see the topic Pointer types . 有关指针的更多信息,请参阅指针类型主题。

Good Answers. 好的答案。 I would add that Java depends on usage of stack or heap memory locations. 我想补充一点,Java依赖于堆栈或堆内存位置的使用。 C# does as well. C#也是如此。 The idea of using raw pointers is an addition to C# that comes from it's C code background. 使用原始指针的想法是C#的一个补充,它来自它的C代码背景。 Although C# and C / C++ are not the same code language, they do share some commonalities semantics. 虽然C#和C / C ++不是相同的代码语言,但它们确实共享一些共性语义。 The idea of using "unsafe" code allows you to avoid keeping large objects on the heap where memory is limited to around 2GB per runtime instance (for C# per CLR, for Java per JVM instance) without incurring dramatic performance degradation due to garbage collection. 使用“不安全”代码的想法允许您避免在堆上保留大对象,其中内存限制为每个运行时实例大约2GB(对于每个CLR的C#,对于每个JVM实例的Java),而不会因垃圾回收而导致性能急剧下降。 In some cases you can use C#'s ability to leverage unsafe or manually managed memory pointers to get around the fact there are not near as many third party tools for problems like caching outside of the heap. 在某些情况下,您可以使用C#的能力来利用不安全或手动管理的内存指针来解决这样的事实,即在堆外部缓存等问题的第三方工具并不多。

I would caution that if you do use unsafe code be sure to get familiar with "Disposable Types" and "Finalizers". 我会提醒您,如果您使用不安全的代码,请务必熟悉“一次性类型”和“终结器”。 This can be a rather advanced practice and the ramifications of not disposing of your objects properly is the same as with C code ... the dreaded MEMORY LEAK. 这可能是一个相当先进的做法,并且没有正确处理对象的后果与C代码相同......可怕的MEMORY LEAK。 Repercussions are you run out of memory for your app and it falls over (not good). 你的应用程序内存不足会导致内存不足(不好)。 That is why C# does not allow it by default and that you need to override any usage of manually controlled pointers with the "unsafe" keyword. 这就是为什么C#默认不允许它,并且您需要使用“unsafe”关键字覆盖任何手动控制指针的使用。 This ensures that any manually handled memory is intentional. 这确保了任何手动处理的内存都是有意的。 Put on your C-code hat when dealing with the "unsafe" keyword. 在处理“unsafe”关键字时,请加上您的C代码帽。

A great reference to this was in the chapter "Understanding Object Lifetime" in "Pro C# 2010 and the .Net Platform" by Andrew Troelsen. 对此的一个很好的参考是Andrew Troelsen撰写的“Pro C#2010和.Net平台”中的“理解对象生命周期”一章。 If you prefer online references see the MSDN Website Implementing Finalize and Dispose to Clean Up Unmanaged Resources 如果您更喜欢在线参考,请参阅MSDN网站实施最终确定和处理以清理非托管资源

One final note - Unmanaged memory is released in the finalizer portion of your object (~ObjectName(){...}). 最后一点 - 非托管内存在对象的终结器部分释放(~ObjectName(){...})。 These patterns do add overhead to performance so if you are dealing with lower latency scenarios you may be best served by keeping objects light. 这些模式确实会增加性能开销,因此如果您处理较低延迟的情况,最好通过保持对象轻松来实现。 If you are dealing with human response then you should be fine to consider this where absolutely necessary. 如果您正在处理人类反应,那么您应该在绝对必要的情况下考虑这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM