Jump to content
dormky

How can I force a record to be allocated on the heap ?

Recommended Posts

37 minutes ago, JiyaHana said:

You can try with the GetMem function to dynamically allocate memory for the record.

@JiyaHana Please read the thread before replying. That solution was already proposed.

Share this post


Link to post
Posted (edited)
1 hour ago, JiyaHana said:

You can try with the GetMem function to dynamically allocate memory for the record.

Problem with this is that if the record has any managed types, then they won't be properly initialised/finalised when using GetMem/FreeMem. This is what New/Dispose brings.

Edited by David Heffernan
  • Like 1

Share this post


Link to post
26 minutes ago, Lars Fosdal said:

That solution was already proposed.

Actually, I think that this was the first mention of GetMem in the thread.

Share this post


Link to post
2 minutes ago, David Heffernan said:

Actually, I think that this was the first mention of GetMem in the thread.

You are right.  I didn't consider the differences between GetMem and New.

Share this post


Link to post
On 12/11/2023 at 3:35 AM, dormky said:

I have a very, very large record that may cause memory issues for the stack if I use multiples instances of it in a procedure. I'd like to force delphi to allocate it on the heap so this doesn't happen.

I need it to stay a record, it can't be a class. I have no problem with doing a bit of manual work in the procedure to get this, it doesn't have to be something baked in the framework and invisible to me as a dev.

 

Depending on what you are trying to do, keeping records on the heap could become an anti-pattern and cause problems. For one, your records could be duplicated on assignments, on the stack, and if your application relies on their consistency, bugs can creep in. Unlike languages like Rust and Swift, all variables in Delphi are mutable. If I needed a large dataset on. the heap, I would either wrap the records in a class or define a class, and in order to maintain their integrity, I would use interface references to access them and avoid memory leaks. Just my two cents.

Share this post


Link to post
3 hours ago, Navid Madani said:

For one, your records could be duplicated on assignments

So what would be the problem with that? That's what happens with vakue types. 

 

3 hours ago, Navid Madani said:

I would use interface references to access them and avoid memory leaks

Why would interfaces be needed to avoid memory leaks? 

Share this post


Link to post
35 minutes ago, David Heffernan said:

So what would be the problem with that? That's what happens with vakue types. 

 

Why would interfaces be needed to avoid memory leaks? 

Value types are copied unless passed by reference. That can impact performance. Classes and interfaces would be more efficient. Interfaces can emulate data immutability and prevent bugs. Interfaces obviate the need for try-finally blocks, keep code cleaner and easier to maintain. Interfaces can prevent memory leaks. It is not always a simple case of memory allocation/de-allocation with records on the heap. There can be issues with access violations, and hard to detect bugs if record pointers are accessed but point to invalid data. Again, I said that is what I do when using Delphi as opposed to C.

Share this post


Link to post
Posted (edited)
On 1/2/2024 at 11:21 PM, Navid Madani said:

Value types are copied unless passed by reference. That can impact performance.

When performance is an issue, pass by reference then. Presumably you are happy to use value types like integer? Or do you shun all value types? 

On 1/2/2024 at 11:21 PM, Navid Madani said:

Interfaces can emulate data immutability and prevent bugs.

Prevent what bugs? Code with interfaces can have bugs too. So it's not some magic solution. 

On 1/2/2024 at 11:21 PM, Navid Madani said:

Interfaces can prevent memory leaks.

Code using interfaces can have leaks. 

On 1/2/2024 at 11:21 PM, Navid Madani said:

Interfaces obviate the need for try-finally blocks,

They are still there, the compiler writes them. 

On 1/2/2024 at 11:21 PM, Navid Madani said:

It is not always a simple case of memory allocation/de-allocation with records on the heap.

It's the exact same pattern as used with classes. It's well known and easy to follow. 

On 1/2/2024 at 11:21 PM, Navid Madani said:

There can be issues with access violations, and hard to detect bugs if record pointers are accessed but point to invalid data.

This is true. But it's simple enough to flow the rules and avoid this. 

Edited by David Heffernan
  • Like 2

Share this post


Link to post
Thanks, David. No, I don't shun any value types, but we're talking about large record sets, too large for the stack. I was referring to bugs that creep in when the integrity of (mutable) data on the heap is not guaranteed, when variables are mutable. Certainly, records can emulate data integrity patterns with private fields, but that approach is not front and center with Delphi records. 
Interfaces too can cause memory leaks, and be complicated when weak references are needed. But again, it's an overall safer pattern in Delphi, at least in my experience. Interfaces also help write testable and more easily maintainable code by keeping things decoupled. And yes, try-finally blocks are written by the compiler, but compilers ultimately write machine code. That's the whole purpose of using a high-level language: so we don't have to write all that code. It helps keep things readable. 
I agree that it's the same basics with memory allocation and release patterns. But again, different languages implement them in different ways, and some patterns are more idiomatic for a specific language, as in this case. I think our discourse is more over language semantics than technical. While I understand and appreciate your points, I am not convinced to change my approach to large amounts of data on the heap.

Share this post


Link to post
On 1/2/2024 at 3:57 PM, Lars Fosdal said:

@JiyaHana Please read the thread before replying. That solution was already proposed.

I'm sorry but firstly I written about GetMem function. 

Share this post


Link to post
On 1/2/2024 at 8:32 PM, Navid Madani said:

Depending on what you are trying to do, keeping records on the heap could become an anti-pattern and cause problems. For one, your records could be duplicated on assignments, on the stack, and if your application relies on their consistency, bugs can creep in. Unlike languages like Rust and Swift, all variables in Delphi are mutable. If I needed a large dataset on. the heap, I would either wrap the records in a class or define a class, and in order to maintain their integrity, I would use interface references to access them and avoid memory leaks. Just my two cents.

Believe me I would love to move away from this pattern, but unfortunately we have decades-old data stored like this, with the whole rest of the program built around it. It's too late ; the only thing I can do now is make it as safe and as readable as possible for future generations, lol.

Share this post


Link to post

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

×