Jump to content

Memory Management

Hi P

Out of pure curiosity, regarding memory management, I recall to have read that some programming languages (i.e Java) automatically manage the memory, whereas in C (I think...) you have to do it yourself.

 

Having said that, is there any advantage on manually managing memory (like in C) over letting , for example Java, do it by itself?

 

I just want to know the big picture behind manually managing memory.

 

Thank you! :)

 

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, Hi P said:

I just want to know the big picture behind manually managing memory.

Realistically, to an experienced developer it doesn't matter. On a desktop PC, only applications requiring the absolute highest performance can actually benefit from C type memory management, and even then, you need extremely experienced developers to not make the problem worse. Think writing a program that manages a section of memory using malloc/free to emulate a collection of arrays vs an actual collection of arrays created using the new operator. The first can be more performant if and only if there is a huge number of arrays and the developer is good enough to optimize it. The second is much easier to maintain, modify, and use.

The tactic that most modern languages like C# or Java use is to show a programmers model where everything acts like it's on the free store (i.e uses the new operator). Then the compiler figures out whether to place things on the stack or in the free store. According to Eric Lippert, an ex developer of C#, the tactic that C# uses is to place everything that can possibly be placed on the stack, on the stack, regardless of how or where the object was initialized. Of course, that is the CLR stack, which is not necessarily implemented as an actual stack on the processor.

 

With embedded systems, sometimes manual memory management is beneficial from a space consumption perspective, other times it's required because toolchains for languages other than C might not actually exist for that processor.

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

Java makes it easier for some things (by default passes objects by reference) but C gives you a bit more control so it’s easier to tell the computer how you want to manage memory. 

I don’t think java has pointers so to keep track of an array or something you need a new number variable to then find the slot in the array. 

In C you can store the address and get there almost directly; then iterate the memory address instead of a number that would represent the index location in the array in system memory. 

 

This isn’t really necessary as a game like Minecraft runs really fast anyway. There’s no real problem. Even blender is written in Python. 

Link to comment
Share on other sites

Link to post
Share on other sites

15 hours ago, Hi P said:

Out of pure curiosity, regarding memory management, I recall to have read that some programming languages (i.e Java) automatically manage the memory, whereas in C (I think...) you have to do it yourself.

 

Having said that, is there any advantage on manually managing memory (like in C) over letting , for example Java, do it by itself?

 

I just want to know the big picture behind manually managing memory. 

 

Thank you! :)

 

I personally don't feel much for garbage collectors. Memory is just another resource. If you can't be bothered to free the memory you no longer use, why would you be bothered closing your files or closing your sockets?

 

C++ RAII techniques allow you to effectively manage *all* kinds of resources, not just memory. 

 

But you're somewhat poking at a holy war here, thread lightly.

Link to comment
Share on other sites

Link to post
Share on other sites

6 hours ago, Unimportant said:

C++ RAII techniques allow you to effectively manage *all* kinds of resources, not just memory.

But you're somewhat poking at a holy war here, thread lightly.

Lol, yea no bad intentions, just curiosity though

 

Could you elaborate on what you mean by all kinds of resources?

Link to comment
Share on other sites

Link to post
Share on other sites

9 hours ago, Unimportant said:

I personally don't feel much for garbage collectors. Memory is just another resource. If you can't be bothered to free the memory you no longer use, why would you be bothered closing your files or closing your sockets? 

That's a dangerous view to have. There is a reason that some of the best minds in the world build languages that alleviate the need to do manual memory management.

Even for the most seasoned and experienced professionals, manual memory management is often full of surprises, and surprises lead to errors and inefficiencies.

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

6 hours ago, straight_stewie said:

Even for the most seasoned and experienced professionals, manual memory management is often full of surprises, and surprises lead to errors and inefficiencies.

To each his own. C++ isn't garbage collected yet the entire industry seems to manage. RAII systems have been built to handle resource management. Like i said before, there's lots of resources to worry about; file handles, network connections, mutexes, etc... I don't see why memory would somehow be any different.

Link to comment
Share on other sites

Link to post
Share on other sites

11 hours ago, Hi P said:

Could you elaborate on what you mean by all kinds of resources?

Files should be closed when you're done with them. Systems can lock up just as hard due to running out of file handles as it can due to running out of memory. Mutexes should be released when you're leaving a critical section, etc etc. Anything that must be acquired/opened/built that should be released/closed/destroyed once you're done with it qualifies as a resource. RAII treats all these things in the same way, memory is nothing special. I don't see how programmers that depend on a garbage collector like a crutch would somehow suddenly find the discipline to clean up all their other resources that a garbage collector does not handle.

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

The biggest problem with C/C++ is working with pointers. Most of the problems you run into with the language is dealing with pointers, not how the code actually works. When Sun started Java they basically said, "That's the biggest problem so we're going to get rid of it!" C# was supposed to be Microsoft's answer to Java so I don't think you can do any of the memory access in that language either, but I'd admit I'm not as experienced with C# as I am with C/C++, Java/Kotlin and Obj-C/Swift... I've never written a program that was so vital that I had to really worry about it. You really just need to keep a heads up for what's called retain cycles in Obj-c/Swift. It's where two object point to each other and you "Delete" them but since they hold references to each other they're not actually deleted, just release so you can't control them anymore, but the are still using memory, i.e. a memory leak.

Link to comment
Share on other sites

Link to post
Share on other sites

On 4/5/2019 at 4:45 PM, Hi P said:

Out of pure curiosity, regarding memory management, I recall to have read that some programming languages (i.e Java) automatically manage the memory, whereas in C (I think...) you have to do it yourself.

 

Having said that, is there any advantage on manually managing memory (like in C) over letting , for example Java, do it by itself?

The biggest ones are:

  • Resource requirement. Garbage collection can require more memory to use, outstripping the benefit of preventing memory leaks in the first place.
  • Performance. You don't have a garbage collection system running in the background taking up CPU cycles that could've been spent on your application.
  • Predictability. While dynamic memory allocation itself doesn't have a guaranteed run time, garbage collection can introduce further unpredictability. Garbage collection also stalls the program from running.

However, while these were issues in the beginning of garbage collectors, it has since been improved where these issues are minimized.

 

11 hours ago, Unimportant said:

Files should be closed when you're done with them. Systems can lock up just as hard due to running out of file handles as it can due to running out of memory. Mutexes should be released when you're leaving a critical section, etc etc. Anything that must be acquired/opened/built that should be released/closed/destroyed once you're done with it qualifies as a resource.

Thing is with resources like those is the expected time to live can either be extremely short, such as reading the contents of a file, or for the life of the program, such as taking a network socket to listen for connections. Also when something breaks because an app is abusing a resource, it tends to be obvious what resource is the problem. This can help narrow down what part of the app is breaking.

 

If it's a memory leak, it can be hard to figure out where exactly the issue is occurring. Say I have an interprocess messaging system using a library which dynamically allocates a chunk of memory to store incoming messages. However, it isn't guaranteed when the process receiving the message will get around to handling it. As such, the messaging system makes no assumptions on when to free the message, it leaves it up to the application to do so. And when a developer who doesn't know they were supposed to call the release function whenever they processed the message doesn't do so, that leaves you with a leak. Because no explicit allocation call was made in the application code, I can't simply do a "make sure every malloc/new/whatever has a corresponding free/delete/whatever" to track down the leak.  In other words memory resources tend to be passed around like candy and who's supposed to clean up after the party can be vague.

 

Quote

RAII treats all these things in the same way, memory is nothing special. I don't see how programmers that depend on a garbage collector like a crutch would somehow suddenly find the discipline to clean up all their other resources that a garbage collector does not handle.

Which is a nice feature to have in OOP, where deleting an object automatically calls a function so you can have every clean up routine you need in that function. But you can't do this in C outside of non-standard libraries.

Link to comment
Share on other sites

Link to post
Share on other sites

14 hours ago, Mira Yurizaki said:

Which is a nice feature to have in OOP, where deleting an object automatically calls a function so you can have every clean up routine you need in that function. But you can't do this in C outside of non-standard libraries.

I'm talking C++ off course. It's indeed a nice feature to have, basically one ties the lifetime of any dynamic resource to a automatic object on the stack. And since it'd hard to leak stack it's hard to leak the resources tied to them. C++11 provided the last missing link, being able to move objects on the stack cheaply. Many a garbage collected language has no concept of destructors. I guess looking at the problem trough such a lens makes it hard to understand how you'd ever do without the garbage collector.

 

For C there's some platform specific help, such as gcc's cleanup attribute, but nothing standardized afaik.

14 hours ago, Mira Yurizaki said:

Thing is with resources like those is the expected time to live can either be extremely short, such as reading the contents of a file, or for the life of the program, such as taking a network socket to listen for connections. Also when something breaks because an app is abusing a resource, it tends to be obvious what resource is the problem. This can help narrow down what part of the app is breaking.

 

If it's a memory leak, it can be hard to figure out where exactly the issue is occurring. Say I have an interprocess messaging system using a library which dynamically allocates a chunk of memory to store incoming messages. However, it isn't guaranteed when the process receiving the message will get around to handling it. As such, the messaging system makes no assumptions on when to free the message, it leaves it up to the application to do so. And when a developer who doesn't know they were supposed to call the release function whenever they processed the message doesn't do so, that leaves you with a leak. Because no explicit allocation call was made in the application code, I can't simply do a "make sure every malloc/new/whatever has a corresponding free/delete/whatever" to track down the leak.  In other words memory resources tend to be passed around like candy and who's supposed to clean up after the party can be vague.

I don't see how the lifetime of a resource makes a difference. If you need to clean it up you need to clean it up. The fact that it might live longer does not move the cleanup code to some obscure corner where you might forget about it. It's supposed to be right there in the destructor right underneath the constructor where you've acquired it. (And because the standard library offers most resource handles you'd need pre-made anyway you probably won't even have to write the destructor most of the time).

 

Your example somewhat reveals you don't know how modern C++ is supposed to work. If the library call that dynamically allocates some memory wants the caller to take ownership (and thus responsibility for deleting it) it would return a std::unique_ptr<T>. The unique_ptr will clean itself up when it goes out of scope or is overwritten. If the library call does not want to transfer ownership it simply returns a raw pointer.

 

If you have a old library that still does things the old way and returns raw owning pointers then it's trivial to write a wrapper that immediately puts everything in a unique_ptr. (or check if there's an update for this 8+ yr old library :) )

Link to comment
Share on other sites

Link to post
Share on other sites

52 minutes ago, Unimportant said:

Many a garbage collected language has no concept of destructors

Can you name one?

Off the top of my head, GC languages that have destructors are Python, C#, Java, Perl, Objective-C, Swift, VB.NET, and Visual Basic.

 

Trivially, a language which relies on Garbage Collection for memory management is poorly implemented at best if it does not provide some construct for defining type-specific de-initializers.

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

4 hours ago, Unimportant said:

-Snip-

You're making the assumption of the environment I work in, which yes is a huge gap in information. But let's put it this way: I don't have the luxury of the latest and greatest. It's great if you have total or a very high degree of control over the source code and the direction you want to take it, but I don't have that. I have to work with what I'm given and I can't go "I'm going to update to the latest and greatest," because the scope of work would be massive to ensure that everything still works.

 

Also the things I work on is mostly in C. So whatever you're suggesting has no use for me. Not that I don't appreciate them.

 

EDIT: Don't take the "latest and greatest" thing too literally. Yes I know unique_ptr is a relatively old feature.

Link to comment
Share on other sites

Link to post
Share on other sites

3 hours ago, Dat Guy said:

Java does not have destructors. Finalizers are not exactly the same thing.

They sort of are the same, or atleast, the compilers for languages that support a multiplicity of object de-initializer techniques generate the same code for each type.

In the advanced OOP languages, the terms destructor and finalizer only differ by convention. In atleast one language that offers both, C#, the compiler converts the destructor into a finalizer method with the statements surrounded in a generated try/catch statement.

 

The finalizer, either generated or explicit, is then automatically called by GC.

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

Yes, and internally, everything is machine code anyway. That was not the point, I guess.

Write in C.

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, Dat Guy said:

Yes, and internally, everything is machine code anyway. That was not the point, I guess.

That has nothing to do with what I said, and is not an extension of my point. In Java, you are also allowed to not define a finalizer/destructor. In this case, the Garbage Collector simply marks the memory the object resides in as empty and moves on.

My only point was that an argument between the terms Finalizer and destructor is purely an argument about semantics. The two are identical in function and GC treatment.

ENCRYPTION IS NOT A CRIME

Link to comment
Share on other sites

Link to post
Share on other sites

At the end of all this, regarding resource management, the biggest difference I'm finding between C and the other languages regarding memory management is C doesn't automatically do things for you. It's easy to say resource management is easy when certain things are automatically done for you. Objects get destroyed either because they fell off the stack or were explicitly called? The language supports the feature of automatically doing something when that happens. It doesn't matter if the actual cleanup routine needs to be written or if there's a GC to do it for you, the fact that something automatically happens is all you need.

 

Yes you can sort of kludge this in C using clang and gcc non-standard features, but it's just that, a kludge. If the idea is to run a cleanup routine before returning in order to guarantee its deallocation regardless of the circumstance, this can present a problem: http://nibblestew.blogspot.com/2016/07/comparing-gcc-c-cleanup-attribute-with.html

 

The author also points something out:

Quote

By reliability we mean that the compiler must handle all cases and the developer must not need to write any manual management code.

 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×