2

I need to change the length of the array dynamically.Right now the code looks like this:

VAR
   arrData : ARRAY[1..200] OF INT;
   length  : INT := 200;
END_VAR

The size of the array depends on the length variable.Here the value of length variable can be changed during runtime using the VISU(gui). So if I change the value of the length = 180 then 20 bytes of arrData are unused.Is there a way to declare the array as variable length similar to vectors in c++ such that the memory is not assigned during declaration but during runtime.

Edit: How to deallocate the memory safely?

PROGRAM MAIN
VAR
   arrData : POINTER TO INT;
   length : INT := 200; // can be changed at runtime
   bNew : BOOL := TRUE;
   oldLength : INT;  // to hold the old length variable
   isInit : BOOL := FALSE;
END_VAR

IF NOT isInit THEN
   oldLength := length; // initialise only once
   isInit := TRUE;
END_IF

// if length is changed during runtime then delete the array 
IF oldLength <> length THEN
   IF arrData <> 0 THEN
      __DELETE(arrData);
      bNew := TRUE;
   END_IF
   oldLength := length;
END_IF

// during the first run or when the length is changed
IF bNew THEN
   arrData := __NEW(INT,length);
   bNew := FALSE;
END_IF

// deallocate the memory when the MAIN program goes out of scope
// as we are not deleting the array when the length variable is not    
// changed during runtime


END_CASE   

1 Answers1

2

The way to do it is to use __NEW __NEW in Infosys

pMyPointer := __NEW(INT, length);

__NEW will return a pointer to first element of an array. You can access latter elements by offsetting this pointer.

You can check if length was changed by comparing value from this and previous cycle. If so, __DELETE the old array and initialize a new one.

Edit:

I think, that you get your error the moment TwinCAT runtime is stopped, as the momory allocated by __NEW is not freed at that point.

Your code should be placed not in a Program (PRG) but in a Function Block (FB). The reason for that is that you need to implement FB_exit method (This method is called implicitly when FB instance is destroyed, i.e. when stopping TwinCAT runtime like you do by activating configuration). There is no equivalent method for a PRG as far as I know.

To do this:

  1. Create a new FB, instantiate it and call it in your MAIN and move your code from MAIN to the FB
  2. Add a FB_exit method to this FB. Exact naming is crucial
  3. In your FB_exit method write the following code:
IF __ISVALIDREF(arrData) THEN
  __DELETE(arrData);
END_IF

This method will be called every time you stop your runtime and free the memory.

Links to Infosys:

Jacek Domański
  • 563
  • 3
  • 7
  • I tried your method. If I deallocate the memory using __DELETE by checking if the length has varied then it throws an error **failed to free dynamically allocated memory block at address 0xdeadbeef**. Twincat3 expects to deallocate memory when we exit from MAIN program ie if the MAIN program goes out of scope.How can I do this? – shakingwindow Oct 26 '22 at 14:47
  • Please edit your question and add your code, I'll see what I can do :) – Jacek Domański Oct 26 '22 at 18:44
  • @shakingwindow When exactly does the "failed to free dynamically allocated memory block at address 0xdeadbeef" error occur? – Jacek Domański Oct 26 '22 at 20:19
  • When I click on command active configuration. You can see this video : [link](https://www.youtube.com/watch?v=Fo8CT5HZkjw) – shakingwindow Oct 26 '22 at 20:42
  • @shakingwindow edited my answer. Also - I already wrote this comment few hours ago and it got deleted for some reason – Jacek Domański Oct 27 '22 at 18:48
  • I could not move the code from MAIN to FB as I have VAR_RETAIN variables and twincat3 throws an error if I move the code as VAR_RETAIN can not be defined in FUNCTION BLOCK. And these VAR_RETAIN variables are essential which are used in the other part of the MAIN program. Does MAIN have this kind of MAIN_exit function? – shakingwindow Oct 28 '22 at 13:10
  • There is no exit method for programs (PRG) as far as I know. You can still declare your variables in MAIN and inject them to FB instance using VAR_IN_OUT or pointer input. Also - are you sure your spelling is correct? It should be VAR RETAIN, not VAR_RETAIN – Jacek Domański Oct 28 '22 at 16:23
  • Yeah I meant VAR RETAIN. I solved the error like this. I declared the array as VAR GLOBAL. Then I created function block FB and method FB_exit and inserted the code as you mentioned. So since the array is VAR GLOBAL it can be accessed in FB_exit and when MAIN goes out of scope, the method FB_Exit goes out of scope too. Do you recommend this implementation? – shakingwindow Nov 02 '22 at 16:02
  • 1
    If you'd like my opinion on your code, I'd like to see the code first – Jacek Domański Nov 02 '22 at 21:23