blog icon indicating copy to clipboard operation
blog copied to clipboard

Manual Memory Management

Open worksofliam opened this issue 5 years ago • 0 comments

This is quite a new topic for me, but over the last few days I've been using them more and more so I thought I'd write about it. In this blog I will be using STRDBG since I recently stopped using Rational Developer for i for development.

In this, we'll talk about allocating space for null-terminated strings in RPG. It's going to cover the Pointer type, %Alloc, Dealloc and %Str

Pointer Type

The pointer type is quite simple. It holds a value which points to somewhere in memory. When you define a pointer, the initial value will be *Null.

Next, I'm going to compile this program and start debugging it so we can see what a pointer value looks like.

Dcl-S Text   Char(32);
Dcl-S Pointy Pointer Inz(*Null);
//I could of also used Inz(%Addr(Text))

Text   = 'Hello WorksOfBarry blog!';
Pointy = %Addr(Text);

//Breakpoint here.

*InLR = *On;
Return;

When you STRDBG this program, make sure you put a breakpoint after the comment says:

> EVAL Pointy
POINTY = SPP:D9858621D4002540

> EVAL Pointy:c 20
POINTY:c 20 = 'Hello WorksOfBarry b'
//This shows the next 20 bytes from the pointer 
//(:c for characters, 20 for length)

%Alloc and Dealloc

I've found that some people find memory allocation can be really confusing, but personally I find it very simple.

Just some things to remember:

  • When you allocate space, it will allocate within a heap inside of the program's activation group.
  • You are able to pass pointers to programs which run in different activation groups to access heaps in different activation groups.
  • If you forget to deallocate memory, all memory within the activation group is deallocated when it ends.

%Alloc takes one parameter, which is a numeric length. I have found that if you're using alloc to work with strings, you should add one to your length. This is to support the null terminator.

Let's take my name for example, which is "Liam Allan". That's 10 characters, including the space, which is 10 bytes - but we need to have an extra byte for the null terminator.

image

Deallocating is very important. The dealloc operation allows you to deallocate the memory you have allocated and has two extenders:

  • E for error. If this extender is used, dealloc will never crash and will instead update the value of %Error.
  • N for *Null. This means that when the memory is deallocated, it will set the pointer back to *null.

I like to use both!

Here's a working example:

Dcl-S Pointy Pointer Inz(*Null);
Pointy = %Alloc(11);
Dealloc(ne) Pointy;

%Str

Great! So now we know how to create space, how do we use this space? With %Str of course! %Str has two uses - to make this simple, it can be used as a getter and setter.

Setter

The setter should take a second value, which is the length you're assigning - it does not have to match the length, it's just preference for me. Just know that the last character will always be the null terminator.

Dcl-S Pointy Pointer Inz(*Null);

Pointy = %Alloc(11);

%Str(Pointy:10+1) = 'Liam Allan';
//Notice the +1 for null-terminator

Dealloc(ne) Pointy;

Getter

Getting the value out is nice and simple. One thing to remember is that %Str will get all characters at the pointer up until the null-terminator.

image

You can also pass in a second parameter, which is the length to get - in this example I will use length of the text I assigned when printing with Dsply.

Dcl-S Name   Char(10);
Dcl-S Pointy Pointer Inz(*Null);

//Allocate and assign
Pointy = %Alloc(11);
%Str(Pointy:%Len(Name)+1) = 'Liam Allan';

//Give Name field a value
Name = 'Liam Allan';

If (%Str(Pointy) = Name);
  DSPLY %Str(Pointy:10);
ENDIF;

Dealloc(ne) Pointy;

End

Well I hope this was a somewhat interesting guide into null-terminator strings and pointers. I actually had fun writing it!

worksofliam avatar Jul 07 '19 01:07 worksofliam