Memory not cleaned (with Struct)

Hi,

in a customization job, I make use of 2 different Arrays of Struct, like

/*code snippet

Array = new Array(types::Class);

Array2 = new Array(types::Class);

Array.value(id, new Struct(types::real, “param1”, types::Integer, “param2”));

Array2.value(id, new Struct(types::string, “param3”, types::Integer, “param4”));

*/

first array holds in real 23 values in the struct (23 seems to be the limit in Struct)

So thats why I created a 2nd Array, cause I have more values.

What I experience is that after making a modification and start the code again, some values of the Struct are old values.

It looks like the Structs are not fully cleaned or initialized in memory.

Is this a memory leak?

Is finalize() the way to fix this, if yes how to use finalize exactly?

What can be the problem of this behaviour?

Thanks

Why are you using Struct at all, especially if you’re saying that it doesn’t meet your requirements?

If you have a bunch of named values, why don’t you design a class for that? If you don’t know them at design time, you can use a Map object to hold name-value pairs.

Well…because I know how to handle struct.

And am not into design classes.

I get the concept of classes, but to design from zero is not my cup of tea (yet)

Could you ls give me a headstart with a class for a bunch of value pairs?

Thanks

It’s a critical piece of knowledge - object-oriented programming (OOP) is all about objects (= instances of classes), therefore understanding them is crucial. If you don’t know the basics, you simply must go and learn them. Fortunately internet is full of great resources.

Also realize that it’s nothing specific to AX and AX resources won’t teach you OOP. But that’s not a problem; you can learn concepts from books written for other languages (e.g. I got the basics from Thinking in Java).

When you need something specific to AX, you can consult documentation. I would also highly recommend downloading and reading Inside Dynamics AX 4.0 (it’s free!). Yes, it’s for a newer version, but many things are the same and you’ll learn a lot from it.

Now to the actual implementation. The class will be very simple - it will have several variables in ClassDesclaration, holding the values. Such as:

str name;
real price;

But these variables can’t be accessed by other classes, therefore you need methods allowing to read and modify values from outside.

For each variable, you could write a “get” method returning the current value and a “set” method changing it, but the usual approach in AX is combining it to a single “parm” method. Like this:

public str parmName(str _name = name)
{
    name = _name;
    return name;
}

When you have that, you can create an instance of your class and use the methods to manipulate values. Because methods has meaningful names, it’s easy to understand what’s going on:

MyClass o = new MyClass();
o.parmName("Puck");

Note that the variables may hold other objects too, not just primitive data types such as int.

Therefore if you have values that logically belongs together, you can put them all together to a separate class, rather than mixing them with unrelated values. You’ll later learn how important it is to split the application to logical pieces.

Thanks Martin for the headstart.

This concept is totally clear for me and implementing it right now.

Thanks for the links too, it will give me a deeper understanding of Classes, so in future I can create it myself and be sure it’s done good.

Question solved!

I understand what you’re saying.

I can create also Extended datatypes, enums and primitive datatypes etc in the Class.

But I can do this in 1 class I guess?. Those are all different types, belonging to the same process.

Or do you mean to make a separate class for the enums in the process and a separate for the extended datatypes?

What’s the benefit of that?

Thanks

You can use any type inside a class. A few examples:

int             counter;    // number
FileType        fileType;   // enum
UserInfo        user;       // table
InventMovement  inventMov;  // class
List            list;       // collection class

You should group data logically, not based on data types; a class should encapsulate data and logic of a certain logical entity. For example, SysRecurrence class has a unit (SysRecurrenceUnit enum), a start time (number), an end date (date) etc., together with related business logic (e.g. nextDateFromToday() method).

By the way, the usual OOP languages don’t have the concept of tables; everything is a class there. But in AX, you must decide what we’ll be modeled as a class and what as a table (possibly a temporary one).

All clear, thanks for your help!

Now that I’m busy with it.

Should I continue with Array = new Array(types::Class);

And then call Array.value(_id, o.parmname());

Or is there a way to initialize several instances of this same class, and identify those classes by an _id.

I think it should be possible, but where can I find an example of how this is done.

Can you please explain what you’re trying to achieve? Ideally start with telling us a bit about the business requirement you’re dealing with. Then it should be clearer what the technical solution needs to cover.

Of course you can create any number of instances of the same class. Like this:

MyClass c1 = new MyClass();
MyClass c2 = new MyClass();

You can put them into an array if you want, but I don’t see any reason why you would put individual fields into an array. It looks like you stick to the wrong code that you designed before learning about classes. Again, an explanation of what you’re doing would give me a better idea.

Thanks Martin, I will explain:

I want to track values of Commodoties like Oil, electricity and gas.

So it looks like, simplified

Commodity id open high low close valuenow

Oil 1 74.95 78.02 73.00 74.06 73.02

Gas 2 150.34 155 150.34 154.75 154.01

Electricity 3 34.09 44.6 32.00 40.25 40.10

I want to keep track of this in memory, cause database is too slow and variables are much easier.

I want to make decisions based on these prices.

So far I made something for it in an array as you know.

When initializing an external API I give the id during initializing.

So I get prices back, identified by the id and want to keep track of those.

So far I made a matrix with the nested arrays, and later array of structs.

As per your suggestion of creating a class, which is good idea cause I have much more possibilities.

But now stumble upon identify those classes.

So normally it would be myClass.open(74.95)

But am looking for something like

myclass(1) open(74.95)

myclass(2) open150.34)

myclass(3) open(34.09)

Where of course (1) (2) and (3) are the id’s

You can design the classes like this, for example:

CommodityPrice oilPrice = new CommodityPrice();
oilPrice.parmType(CommodityType::Oil);
oilPrice.parmOpen(74.95);

CommodityPrice gasPrice = new CommodityPrice();
gasPrice.parmType(CommodityType::Gas);
gasPrice.parmOpen(150.34);

Of course, there are other options, such as putting the Type to the constructor:

CommodityPrice oilPrice = new CommodityPrice(CommodityType::Oil);
oilPrice.parmOpen(74.95);

I don’t have enough information about the entity to know which design would be the best.

If you want to put the prices to a collection and access them by their indexes, you can use Array, but you put there the whole objects and not individual values.

// Constructing the array
Array pricesArray = new Array(Types::Class);
pricesArray.value(1, oilPrice);
pricesArray.value(2, gasPrice);

// Getting a value
CommodityPrice price = pricesArray.value(2);
real openPrice = price.parmOpen();

Note that you can also use a table. If you want to keep things in memory, simply use a temporary table. And if you need to persist the data, a table is exactly the right thing.

You claim that using tables is complicated, but it’s not the case. Take a look:

// Writing to a table
CommodityPrice oilPrice;
oilPrice.Type = CommodityType::Gas;
oilPrice.Id = 1;
oilPrice.Open = 74.95;
oilPrice.insert();

// Retrieving the data
CommodityPrice price;
select price where price.Id == 1;
real openPrice = price.Open;

Thanks again Martin, I admire your patience around this forum to explain every question in a patience way :slight_smile:

I get the first part, but the end is a big eyeopener, and might be thé solution.[emoticon:c4563cd7d5574777a71c318021cbbcc8]

You say a tempTable is a table only processed in memory??

Well that would be perfect then. The knowledge of working with tables is quite good, so that would be perfect.

I don’t want to use database, because its (too) slow and something in me thinks that’s not good to write read 24/7, many,many times per second the same values…at the same place. I wonder if the HDD will like that. I can be wrong there, but mainly the speed is the most important factor

So with tempTable I have the speed of memory, and the easyness of tables. perfect match! [emoticon:c4563cd7d5574777a71c318021cbbcc8]

Thinking about that, I can make a class of that table and create methods which will populate that data.

I will start a new thread about that cause it got not much todo with the original question. See you there? :wink:

Temporary tables in AX 3 are indeed held in memory, but only if you don’t put much data there (128 KB, to be precise). If you do, it will be stored in a file on disk. Note that a temporary table may exist on either client or server (depending on where you insert the first record) and you should pay attention to it - you want to store the data on the tier where you’ll need them.

But note that database are designed for storing a huge amount of data, efficient querying, running 24/7, for save concurrent access of many users, ensuring data consistency even in case of failure and so on. Don’t try to build a kind of database in the application layer; you won’t do it better than what huge teams of smart people designed, developed and improved for years. Using some local cache may be a good approach, but saying that you won’t use a database server because it’s slow and not good for concurrency doesn’t make a good sense to me.

I strongly recommend that you read a bit about temporary tables before writing code. If you open Inside Microsoft Dynamics AX 4.0 (I gave you a link above), you’ll find the section about temporary starting at page 351.