Recent

Author Topic: How to dispose an array pointer.  (Read 14323 times)

boren

  • New Member
  • *
  • Posts: 25
How to dispose an array pointer.
« on: October 13, 2013, 09:48:35 am »
I have the following program:

Program ArrayPointer;

Type Strname = string[100];

Var Pstr : ^Strname;

Begin

New (Pstr);
Pstr[0]:='ABC';
Pstr[1]:='BCD';
Pstr[2]:='CDE';

Dispose (Pstr);

Writeln ('0=',Pstr[0], '; 1=',Pstr[1], '; 2=',Pstr[2]);
Readln;
End.

The result is: Pstr[1] and Pstr[2] still hold values.

Does it already get free of memory? or Need to code more to get free of memory?

Please help me to code more to get free of memory if need.

Thanks.
Thanks so much!
Boren.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: How to dispose an array pointer.
« Reply #1 on: October 13, 2013, 09:57:12 am »
you are kidding right?
Code: [Select]
StrName = string[100];
is of short string type with a fixed length of 100 characters in other words the strName is an array of 100 characters not strings, so the code
Code: [Select]
New (Pstr);
  Pstr[0]:='ABC';
  Pstr[1]:='BCD';
  Pstr[2]:='CDE';
assumes that the pstr is a dynamic array of strName strings (something along the lines of pstr : ^Array[0..X] of strName;) that have never been initialized to hold more than 1 string. You have effectively create your own buffer overflow.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

boren

  • New Member
  • *
  • Posts: 25
Re: How to dispose an array pointer.
« Reply #2 on: October 13, 2013, 10:24:37 am »
I have so little experience in programming.
I try to program to enter some names in array that has not predefined its length like in PHP.
I see using pointer is a solution. But I am afraid of getting memory leak. And I find pointer is difficult to understand.
I would appreciate it if you can answer my question above more clearly or show me any solution.
Thanks.
Thanks so much!
Boren.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: How to dispose an array pointer.
« Reply #3 on: October 13, 2013, 11:15:13 am »
well as I said in one hand you declare an array of characters with a length of 100 and on the other hand you try to recreate a dynamic array of string with pointers, I wasn't sure what you wanted to do, now that I know your problem : to have an array of strings that can change its length at runtime you simple declare it as
Code: [Select]
var
  MyNameArray : array of string;
begin
end;
that's it, this is a dynamic array of strings with 0 elements the rest is easy use SetLength to allocatee memory eg
Code: [Select]
  setLength(MyNameArray, 100);
that will allocate 100 elements (in this case strings), the length is always in terms of elements/cells the array should have. The dynamic array is reference counted so the moment the count falls to 0 it frees it self so you don't have to thing about it to hard, in any case if you want to release the memory it occupies simple set the length to 0.
« Last Edit: October 13, 2013, 11:17:21 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

andresayang

  • Full Member
  • ***
  • Posts: 124
Re: How to dispose an array pointer.
« Reply #4 on: October 13, 2013, 11:56:26 am »
Hi,

There is a class done for what you would like to do: TStringList.

Why don't you use it ?

Cheers.
Linux, Debian 12
Lazarus: always latest release

Leledumbo

  • Hero Member
  • *****
  • Posts: 8835
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: How to dispose an array pointer.
« Reply #5 on: October 13, 2013, 03:40:32 pm »
Quote
The result is: Pstr[1] and Pstr[2] still hold values.

Does it already get free of memory? or Need to code more to get free of memory?
Dispose, FreeMem, TObject.Destroy, and all other memory freeing functions only mark the memory as being reusable. The memory manager can reuse the memory anytime, and at that time, your value won't be valid anymore. Try creating another pointer and allocate some memory for it right after printing the values, then assign some values to the new pointer and print the previous values again.

boren

  • New Member
  • *
  • Posts: 25
Re: How to dispose an array pointer.
« Reply #6 on: October 14, 2013, 09:33:42 am »
Quote
Dispose, FreeMem, TObject.Destroy, and all other memory freeing functions only mark the memory as being reusable. The memory manager can reuse the memory anytime, and at that time, your value won't be valid anymore. Try creating another pointer and allocate some memory for it right after printing the values, then assign some values to the new pointer and print the previous values again.
So after using Dispose(Pstr); it means the memory for Pstr[0], Pstr[1] and Pstr[2] is reusable, isn't it?

Thank you all.
« Last Edit: October 14, 2013, 09:35:31 am by boren »
Thanks so much!
Boren.

andresayang

  • Full Member
  • ***
  • Posts: 124
Re: How to dispose an array pointer.
« Reply #7 on: October 14, 2013, 10:36:22 am »
 Hi,

You can not do what you are writing:

Code: [Select]
Program ArrayPointer;

Type Strname = string[100];

Var Pstr : ^Strname;

Begin

New (Pstr);
Pstr[0]:='ABC';
Pstr[1]:='BCD';
Pstr[2]:='CDE';

Dispose (Pstr);

Writeln ('0=',Pstr[0], '; 1=',Pstr[1], '; 2=',Pstr[2]);
Readln;
End.

Well, I am not 100% sure about fpc compiler behavior, but if you compile your code with TP7 or Delphi, you will obtain:
- Compilation error (type mismatch char / string)
- Run time error

I'll explain you a little bit why:

Var Pstr : ^Strname; Here you declare a variable of type pointer. So the content of this variable is nothing more than a memory address.
Pstr[0]:= 'ABC'; Here, delphi compiler will give you an error. First of all, you try to assign a string to the variable Pstr, Pstr is a pointer => type mismatch.
The good codding for this should be:
Pstr^[0]:= 'ABC'; But here also, delphi compiler will gives you an error. Pstr^ is a string of 100 Chars., so Pstr^[0] is one char => you try to assign a string to a Char => type mismatch.
What will work is:
Pstr^:='ABC'; In this case, Pstr^[0] will be equal to 'A' ... Pstr^[2]='C';

I hope you understand what I wanted to explain you, again, I am not 100% sure about the syntax fpc allows (maybe when you do Pstr[0] you really assign Pstr^[0], but it is not the "pascal standard" and if you try your codding on another compiler, this time I am 100% sure it will not compile).

Cheers.

And once again, to do what you want to do: having a list of string which can increase / decrease without knowing it maximum / minimum size, you should use the Stringlist class, everything is already codded, you will not have to manage the memory.
Linux, Debian 12
Lazarus: always latest release

Leledumbo

  • Hero Member
  • *****
  • Posts: 8835
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: How to dispose an array pointer.
« Reply #8 on: October 14, 2013, 03:08:26 pm »
Quote
So after using Dispose(Pstr); it means the memory for Pstr[0], Pstr[1] and Pstr[2] is reusable, isn't it?
Yes
Quote
Well, I am not 100% sure about fpc compiler behavior, but if you compile your code with TP7 or Delphi, you will obtain:
- Compilation error (type mismatch char / string)
- Run time error
It's not a compile error, but it's indeed should be a runtime error.
Quote
Pstr[0]:= 'ABC'; Here, delphi compiler will give you an error. First of all, you try to assign a string to the variable Pstr, Pstr is a pointer => type mismatch.
Wrong, Pstr[0] is a string, FPC supports array-like pointer dereference (see Remark in the linked document). Since Pstr is a pointer to string type, Pstr[0] is the string, Pstr[n] exactly equals to (Pstr + n)^.

The only problem with OP's code is that the New() allocates only buffer for string of 100 character (+1 length byte), so only Pstr[0] is valid. Pstr[1] is 101 bytes after Pstr[0] and so on, which by luck, could point to valid memory address (and can be owned by any objects, including system allocated ones) or not. No compiler checking flags can be used since none can detect this anyway.

andresayang

  • Full Member
  • ***
  • Posts: 124
Re: How to dispose an array pointer.
« Reply #9 on: October 14, 2013, 04:03:58 pm »
Quote
Wrong, Pstr[0] is a string, FPC supports array-like pointer dereference (see Remark in the linked document). Since Pstr is a pointer to string type, Pstr[0] is the string, Pstr[n] exactly equals to (Pstr + n)^.

For compile / runtime, I think I was speaking about Delphi compiler, not the fpc one (as I was'nt aware that fpc does the same that C does about pointer)
Linux, Debian 12
Lazarus: always latest release

boren

  • New Member
  • *
  • Posts: 25
Re: How to dispose an array pointer.
« Reply #10 on: October 15, 2013, 06:16:00 am »
Is it a good way to create a dynamic array by my code above?
Quote
Program ArrayPointer;

Type Strname = string[100];

Var Pstr : ^Strname;

Begin

New (Pstr);
Pstr[0]:='ABC';
Pstr[1]:='BCD';
Pstr[2]:='CDE';

Dispose (Pstr);

Writeln ('0=',Pstr[0], '; 1=',Pstr[1], '; 2=',Pstr[2]);
Readln;
End.

If I declare a dynamic array like Astr: array of string[100], then I need to use SetLength while I don't know how many Length yet, so it do not meet my need. And if I use Tstringlist it's good for String, but not for Longint or other type.

If I use similar codes above, I can create a dynamic array (without use SetLength) of any type.
What do you think?

Lazarus & FPC bravo!

Thank you all!
Thanks so much!
Boren.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: How to dispose an array pointer.
« Reply #11 on: October 15, 2013, 06:57:49 am »
1) you either declare the array as dynamic or static not both ee there is no definition of
Code: [Select]
aStr:array of string[100]; its either
Code: [Select]
aStr:Array of string; or
Code: [Select]
aStr:Array[1..100] of string; the first is a dynamic array that can change length at runtime by calling the setlength procedure and second is a static array of 100 elements with out the ability to change its size at runtime.
you choose which one you want to use.

2) If you do not know the number of elements to be put in the array there is no way you can allocate memory for them you can either over shut and allocate more memory than you need or under shut and allocate less memory that you need. In the first case no really harm is done except some wasted memory that will probably never be used, in the second case you are writting outside the memory allocated for your variable what exists next to your memory no one knows might be unallocated memory in which case the next allocate & write set of commands probably will override portion of you existing data but it is most probable that the memory next to yours will have some sort of useful data which you will override and in best case will see unexplainable data or behavior in your application and in worst case the operating system crashes down in it self creating a black hall consuming all your or your clients hard work the last X hours.

In short NO! Don't allocate less memory than needed and use more this is not going to work.

Keep in mind that you can get the size of dynamic array in elements by using
Code: [Select]
length(myArray) and you can extend a dynamic array preserving the existing data (only when extending) with setlength(myArray, OldLength+NewItemCount) eg
Code: [Select]
SetLength(MyArray, Length(MyArray)+5) will extend the existing array with space for 5 more elements
« Last Edit: October 15, 2013, 07:01:32 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Bart

  • Hero Member
  • *****
  • Posts: 5702
    • Bart en Mariska's Webstek
Re: How to dispose an array pointer.
« Reply #12 on: October 15, 2013, 08:38:42 am »
1) you either declare the array as dynamic or static not both ee there is no definition of
Code: [Select]
aStr:array of string[100]; its either
Code: [Select]
aStr:Array of string; or
Code: [Select]
aStr:Array[1..100] of string;

String[100] is ShortString with fixed (max)length of 100, so Array of String[100] should mean a dynamic array of (this type of) shortstrings.

Bart

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: How to dispose an array pointer.
« Reply #13 on: October 15, 2013, 08:59:25 am »
Oh yeah I missed that sorry.
Does it work? I'm under the impression that it shouldn't, you have to declare a type first before using it in the var section like this, it might be my Turbo pascal days surfacing though.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: How to dispose an array pointer.
« Reply #14 on: October 15, 2013, 10:49:38 am »
Is it a good way to create a dynamic array by my code above?

No, this is not a good way, because your use of Pstr[1] and Pstr[2] leads to a memory leak, since the call
Quote
Dispose (Pstr);
does not correctly deallocate the memory areas you have filled with data.
It is safer to declare a specific typed pointer for each area of memory you wish to use, something like this:
Code: [Select]
Program ArrayPointer;

Type TStrname = string[100];
     PStrname = ^TStrname;

Var p1, p2, p3 : PStrname;

Begin
  New (p1);
  p1^:='ABC';
  New(p2);
  p2^:='BCD';
  New(p3);
  p3^:='CDE';

  Writeln ('p1^=',p1^, '; p2^=',p1^, '; p2^=',p2^);

  Dispose(p1);
  Dispose(p2);
  Dispose(p3);

  Readln;
End.

 

TinyPortal © 2005-2018