[fpc-pascal] Community site
You might have noticed that the FPC community site is already down for some time. Since we are retiring the machine running the community site we decided not to migrate the community but add some new boards to the lazarus forum to reduce the need to maintain another bulletin board site. The lazarus forum can be reached at http://forum.lazarus.freepascal.org/index.php?action=forum and it contains now an FPC section. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
[fpc-pascal] List published properties of a class
Hello list. I need to list all published properties declared in a class, iow, removing properties inherited from the parent. Up to now I am iterating typinfo.GetPropList, starting at: GetTypeData(PTypeInfo(TheClass.ClassParent.ClassInfo))^.PropCount; and it works (fpc 2.6.2). TheClass will never receive TObject. Is this the right way? Will such piece of code continue working in future versions of the rtl? ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
> So: don't touch it! ;) > > Regards, > Sven Yep, many thanks for that clear answer. ;-) ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Dynamic arrays, yet another pitfall
On 09.02.2014 19:10, patspiper wrote: On 09/02/14 18:47, Sven Barth wrote: On 09.02.2014 16:34, Flávio Etrusco wrote: In other words: dynamic arrays are like AnsiStrings without the copy-on-write semantics. I'd certainly wish Borland copied the COW semantics :-/ Dynamic arrays have full COW semantics. It seems not: SetLength(A,10); A[0]:=33; B:=A; A[0]:=31; b[0]:=9; WriteLn(a[0], b[0]); // prints 9 and 9 (fpc 2.6.3) Ehm yes... seems that I was mistaken a bit by the dynamic array implementation. *blush* Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Dynamic arrays, yet another pitfall
Am 09.02.2014 18:41, schrieb Jürgen Hestermann: > So it seems there is a copy-on-write *but* only when using SetLength. No. There is no COW, only ref. counting. SetLength just forces an unique instance of the array if needed. > What a very consistent design! There is a very good reason for this design: speed. COW would mean that at every write to a dyn. array element, ref. count must be checked. This would render dyn. arrays useless for a lot of applications due to poor speed. So dyn. arrays with COW simply make no sense. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Dynamic arrays, yet another pitfall
On 09/02/14 18:47, Sven Barth wrote: On 09.02.2014 16:34, Flávio Etrusco wrote: In other words: dynamic arrays are like AnsiStrings without the copy-on-write semantics. I'd certainly wish Borland copied the COW semantics :-/ Dynamic arrays have full COW semantics. It seems not: SetLength(A,10); A[0]:=33; B:=A; A[0]:=31; b[0]:=9; WriteLn(a[0], b[0]); // prints 9 and 9 (fpc 2.6.3) If Jürgen would have provided a full compilable example we could check whether he has a bug in his own code or there is a bug in the compiler as certainly the result of his first code snipped must be length 10 for array "A" and length 20 for array "B". His second example is as expected and as designed. True on both counts. Regards, Stephano ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Dynamic arrays, yet another pitfall
Am 2014-02-09 17:47, schrieb Sven Barth: On 09.02.2014 16:34, Flávio Etrusco wrote: In other words: dynamic arrays are like AnsiStrings without the copy-on-write semantics. I'd certainly wish Borland copied the COW semantics :-/ Dynamic arrays have full COW semantics. Now I am fully confused. It's hard to find out how things work in Free Pascal given the poor documentation. This sentence from http://www.freepascal.org/docs-html/ref/refsu18.html is *very* misleading: "Dynamic arrays are reference counted: assignment of one dynamic array-type variable to another will let both variables point to the same array. Contrary to ansistrings, an assignment to an element of one array will be reflected in the other: there is no copy-on-write." Reference counted? Point to the same array? No copy-on-write? It seems you cannot believe anything from the documentation. You must question every statement. *Everything* can only be determined by writing test programs. I now found a similar posting 5 years ago regarding the same issue: http://lists.freepascal.org/lists/fpc-pascal/2009-February/020198.html Why ist this not part of the documentation? So it seems there is a copy-on-write *but* only when using SetLength. What a very consistent design! ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Dynamic arrays, yet another pitfall
Am 2014-02-09 16:34, schrieb Flávio Etrusco: > In other words: dynamic arrays are like AnsiStrings without the > copy-on-write semantics. I'd certainly wish Borland copied the COW > semantics :-/ Yes. Therefore the issue that I described for dynamic arrays cannot occur for ansistrings. But COW can also be a drawback. Imagine an ansistring within a record of a heavily pointer-connected deeply nested data structure and I want to write a function that gives me back a reference to this string: - function FindMyStringToModify : AnsiString; ... var A : AnsiString; A := FindMyStringToModify; A := 'New String'; - then the change to A will not affect the ansistring in the nested data structure (because of COW). But this is possible for dynamic arrays *if* they are not empty. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Dynamic arrays, yet another pitfall
On 09.02.2014 16:34, Flávio Etrusco wrote: In other words: dynamic arrays are like AnsiStrings without the copy-on-write semantics. I'd certainly wish Borland copied the COW semantics :-/ Dynamic arrays have full COW semantics. If Jürgen would have provided a full compilable example we could check whether he has a bug in his own code or there is a bug in the compiler as certainly the result of his first code snipped must be length 10 for array "A" and length 20 for array "B". His second example is as expected and as designed. Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Dynamic arrays, yet another pitfall
On 09.02.2014 15:34, Jürgen Hestermann wrote: With the following declaration and code: --- var A,B: array of integer; ... SetLength(A,10); B := A; SetLength(B,20); --- both variables A and B point to the same array with 20 Elements. Changing A changes B and vice versa. And again you did not provide a full compilable example. The following code === code begin === program tdynarrtest; var a, b: array of LongInt; begin SetLength(a, 10); b := a; SetLength(b, 20); Writeln(Length(a)); Writeln(Length(b)); end. === code end === results in === output begin === 10 20 === output end === So exactly what I would expect from the COW mechanism. Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Some questions regarding language changes in trunk
On 09.02.2014 16:02, leledumbo wrote: This won't have any negative impact on logical expressions I expect that. I suppose the compiler has a mechanism for this such that "if true then" would work. I haven't explicitely checked it nor looked at the code (no time currently), but it should either be covered by the usual type conversion system or indeed special code. If not that should be considered a bug and reported as such. ;) Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
On 09.02.2014 15:10, Fred van Stappen wrote: > Date: Sun, 9 Feb 2014 13:08:16 +0100 > From: freepas...@ypa-software.de > To: fpc-pascal@lists.freepascal.org > Subject: Re: [fpc-pascal] High() and Low() for empty dynamic arrays > > Am 09.02.2014 13:05, schrieb Fred van Stappen: > > if length(MyArray) > 0 then > > for x := 0 to high(MyArray) do > > MyArray[x].Free; > > > > But, if i use : > > > > setlength(MyArray, 0) ; > > > > would it do the same job ? > > No. Your array contains only references to the objects. The references > where deleted, but the objects remain in memory without any destructor call. > > g > Michael OK, many thanks Michael. Hum, i have a dynamic array of threads. mythread.create has : FreeOnTerminate := True; So, when the thread terminate, it frees the memory too ? (yes/no). Yes, that frees the complete class instance of the thread. And it explain why i get a crash and error message if i try to do, for dynamic arrays of threads : > if length(MyArray) > 0 then > for x := 0 to high(MyArray) do > MyArray[x].Free; Because the threads are already freed (yes/no) ? Exactly. If so, how can i know if MyArray[x] was already freed ? You can't. You must not access MyArray[x] anymore after the thread terminated. When i use: if assigned(MyArray[x]) then MyArray[x].Free; It does not work. Yes, because MyArray[x] is not modified when the thread destroys the class at the end of its life. It doesn't even know that there is a variable that points to the class (class instance variables are basically pointers to the real class instance data). Thus the MyArray[x] still contains the pointer to the class instance data, but the later was already destroyed, so it's no longer valid memory. So: don't touch it! ;) Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
On 09.02.2014 15:46, Jürgen Hestermann wrote: Am 2014-02-09 15:10, schrieb Fred van Stappen: > > if length(MyArray) > 0 then > > for x := 0 to high(MyArray) do > > MyArray[x].Free; As I have learned just recently ;-) this code could be shortened by for x := low(MyArray) to high(MyArray) do MyArray[x].Free; if x is a signed integer. So you would save the length check. Or: for arrayelem in MyArray do arrayelem.Free; > Because the threads are already freed (yes/no) ? Yes, that's tricky. *Some* (managed) data structures like ansistrings and dynamic arrays are freed by the compiler. But if you requested memory by yourself (new, getmem) then you need to clean it up yourself too. I am not sure what applies to threads but I would think that they are managed by the compiler so that a setlength(MyArray,0) would automatically free all (automatically) allocated data. Threads themselves are normal class instances. Normal class instances need to be freed manually (we don't have ARC for class instances yet). Threads however implement a "FreeOnTerminate" property that tells the thread to free itself once it terminates. In this case you must not free the thread yourself (and at best don't touch the class instance variable anymore after you used "Start", because the thread might already be terminated by that point and thus the instance freed). Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Dynamic arrays, yet another pitfall
On Sun, Feb 9, 2014 at 12:34 PM, Jürgen Hestermann wrote: > (...) > With the following declaration and code: > > --- > var A,B: array of integer; > ... > SetLength(A,10); > B := A; > SetLength(B,20); > --- > > both variables A and B point to the same array with 20 Elements. > Changing A changes B and vice versa. > But a slight modification > > --- > SetLength(A,0); > B := A; > SetLength(B,20); > --- > > makes both variables A and B totaly decoupled! Although B is still assigned > to be the same as A each variable is now a separate array with individual > lengths and elements. Variable A has the length 0 and variable B is of > length 20. Changing the length for one of them does no longer change the > length of the other. If someone thinks about dynamic arrays as black boxes > without the need to know the details because they are handled in the > background then he will certainly be baffled by this. > (...) In other words: dynamic arrays are like AnsiStrings without the copy-on-write semantics. I'd certainly wish Borland copied the COW semantics :-/ -Flávio ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Some questions regarding language changes in trunk
> This won't have any negative impact on logical expressions I expect that. I suppose the compiler has a mechanism for this such that "if true then" would work. -- View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Some-questions-regarding-language-changes-in-trunk-tp5718272p5718282.html Sent from the Free Pascal - General mailing list archive at Nabble.com. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
Am 2014-02-09 15:10, schrieb Fred van Stappen: > > if length(MyArray) > 0 then > > for x := 0 to high(MyArray) do > > MyArray[x].Free; As I have learned just recently ;-) this code could be shortened by for x := low(MyArray) to high(MyArray) do MyArray[x].Free; if x is a signed integer. So you would save the length check. > Because the threads are already freed (yes/no) ? Yes, that's tricky. *Some* (managed) data structures like ansistrings and dynamic arrays are freed by the compiler. But if you requested memory by yourself (new, getmem) then you need to clean it up yourself too. I am not sure what applies to threads but I would think that they are managed by the compiler so that a setlength(MyArray,0) would automatically free all (automatically) allocated data. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
[fpc-pascal] Dynamic arrays, yet another pitfall
There is another possible pitfall with dynamic arrays I trapped into which I would like to share. Those who handle dynamic arrays in a virtuoso manner daily may skip this posting of course. But I think for those who never used them before it may be of use. Maybe it can be added to the Wiki (although again I had to make assumptions which may be wrong): With the following declaration and code: --- var A,B: array of integer; ... SetLength(A,10); B := A; SetLength(B,20); --- both variables A and B point to the same array with 20 Elements. Changing A changes B and vice versa. But a slight modification --- SetLength(A,0); B := A; SetLength(B,20); --- makes both variables A and B totaly decoupled! Although B is still assigned to be the same as A each variable is now a separate array with individual lengths and elements. Variable A has the length 0 and variable B is of length 20. Changing the length for one of them does no longer change the length of the other. If someone thinks about dynamic arrays as black boxes without the need to know the details because they are handled in the background then he will certainly be baffled by this. Why is this so? Actually the variables A and B are just (4 byte) pointers to a structure which holds further information of the array (reference counter, length, pointer to the elements...). Setting the length of such a dynamic array to zero means that all data it pointed to will be freed and the pointer is set to NIL. Assigning this NIL-value to another variable of the same type sets this one to NIL too (after removing any potentially existing data of it). Changes for each of these variables no longer affect the other one because they do not point to the same structure anymore. Each has its own structure when adding elements with SetLength. This is especially a pitfall when the dynamic array is part of a complex structure and the reference to it should be given back by function or procedure parameters. It will work as long as the array has elements but fail when all elements have been (temporarily) removed! Under the hood dynamic arrays are similar to pointers to records: --- type MyType = record end; var A,B : ^MyType; --- After --- new(A); B := A; --- B points to the same structure as A and changing A^ changed B^ too. But after --- dispose(A); A := nil; B := A; --- A and B are both nil and --- new(A); new(B); --- would create two different structures with each variable pointing to one of them. The same happens for dynamic arrays. Each length-command changes the structure where the pointer points to but when set to length zero it does not point to anything anymore (is NIL). Afterwards both variables are independend from another. I think this is an important information about dynamic arrays which I was missing from the documentation. Without this knowledge it can be hard to find subtle errors. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
> Date: Sun, 9 Feb 2014 13:08:16 +0100 > From: freepas...@ypa-software.de > To: fpc-pascal@lists.freepascal.org > Subject: Re: [fpc-pascal] High() and Low() for empty dynamic arrays > > Am 09.02.2014 13:05, schrieb Fred van Stappen: > > if length(MyArray) > 0 then > > for x := 0 to high(MyArray) do > > MyArray[x].Free; > > > > But, if i use : > > > > setlength(MyArray, 0) ; > > > > would it do the same job ? > > No. Your array contains only references to the objects. The references > where deleted, but the objects remain in memory without any destructor call. > > g > Michael OK, many thanks Michael. Hum, i have a dynamic array of threads. mythread.create has : FreeOnTerminate := True; So, when the thread terminate, it frees the memory too ? (yes/no). And it explain why i get a crash and error message if i try to do, for dynamic arrays of threads : > if length(MyArray) > 0 then > for x := 0 to high(MyArray) do > MyArray[x].Free; Because the threads are already freed (yes/no) ? If so, how can i know if MyArray[x] was already freed ? When i use: if assigned(MyArray[x]) then MyArray[x].Free; It does not work. Many thanks. Fred ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
Am 09.02.2014 13:05, schrieb Fred van Stappen: > if length(MyArray) > 0 then > for x := 0 to high(MyArray) do > MyArray[x].Free; > > But, if i use : > > setlength(MyArray, 0) ; > > would it do the same job ? No. Your array contains only references to the objects. The references where deleted, but the objects remain in memory without any destructor call. g Michael ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
Hello everybody. I have a question (maybe stupid) about dynamic arrays... Usually, before to close the application, to avoid memory leak, i do : if length(MyArray) > 0 then for x := 0 to high(MyArray) do MyArray[x].Free; But, if i use : setlength(MyArray, 0) ; would it do the same job ? Thanks. Fred ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] fp universal library ?
Hello everybody. Here next episode of the conversion of a useful fp unit into a universal library... After a hard battle, ... i win. But mainly because of the extremely high quality of fpc. The compiler gives me useful tips to realise that unique library. Unique because that dynamic loaded library load other libraries dynamically too. Here some tips : - If you use classes and threads in the unit you want to convert into library, it is a good idea to use dynamic arrays inside the unit. So the user dont have to create that classes in his program, only set length of array inside the unit (without to forget class.create, of course). That mainly for foreign language who will use your library (they could not create your fpc class but if all is done inside the library, no problem). - If you use threads, do not forget to add, in linux , in uses section : cthreads. - Warning : the exported name of function/proc are case sensible... Good to know before to loose (like me) lot of hair. - The most strange (for me) is to create a "Pascal header". Usually, for library, i used h2pas, or c2pas, but here no ;-) . So no big problem to create the wrapper. - Now i have to find : Pas2C, Pas2Java, Pas2Basic, Pas2Net,... (or some brave heart to help me to create wrappers for foreign language.) Conclusion : fpc is FABULOUS. Many thanks to all the creators and congrat for the high care you have done for Libraries compilation too. PS : Im very, very happy, till now, all my wishes become truth with fpc. PS : I have tested the lib and it works ( dynamic load other lib too ). I can play songs with effects perfectly. Now i have to find a way to export-import the data-buffer (dynamic array of float) . But that is for the "custom user DSP" feature, all the bild-in DSP provided by uos-unit are working perfectly. Fred. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
On 2014-02-09 04:11, Jürgen Hestermann wrote: Am 2014-02-08 19:53, schrieb Florian Klämpfl: You didn't have only a question but you made also a proposal for a language change. And when proposing a change it is very usefull to have an example which demonstrates the reason for the change. [snip] Under this impression, what kind of code should I have written? Knowing that you should provide a small but complete example that illustrates the problem that you are proposing a solution to would have caused you to attempt some code. That attempt would probably have brought out the details and assumptions that you overlooked in your original case. And that, in turn, probably would have allowed you to diagnose your problem without bringing it to the developers. So, its' not always about the specific example code. Sometimes it is about the attempt to write it. -- Cheers! Rich Saunders ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Some questions regarding language changes in trunk
On 09.02.2014 03:48, leledumbo wrote: http://wiki.freepascal.org/User_Changes_Trunk#Comparative_operators_can_have_any_result_type Is this a preparation for LINQ-like functionality? Delphi compatibility. But as the example shows you could use it for LINQ-like functionality as well. http://wiki.freepascal.org/User_Changes_Trunk#True_and_False_are_not_keywords_anymore With false and true being integer, how could it be used in an boolean-expression-expected context? e.g. if, while and until condition? Anyway, AFAIK classically Boolean is declared as enum: type Boolean = (False,True); Delphi compatibility (or as is written for that entry: compatibility to other Pascal compilers in general). This won't have any negative impact on logical expressions. Also keep in mind that comparisons with "= True" could lead to wrong results anyway as "True" for Boolean and friends is "1" while "True" for ByteBool and friends is any non-zero value. Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] High() and Low() for empty dynamic arrays
Am 2014-02-08 19:53, schrieb Florian Klämpfl: > You didn't have only a question but you made also a proposal for a > language change. And when proposing a change it is very usefull to have > an example which demonstrates the reason for the change. What code should I have written? I was convinced that Low() and High() both give back zero. I did not ask how High/Low work. I thought I had understood it. So what code should I write? My missinterpretation was based on two facts: 1.) I had switched off range checking 2.) I used a cardinal variable in my for loop That lead to the circumstance that my for loop was entered even when the dynamic array was empty. And then I got an exception when accessing the element with index 0: - var i : Cardinal; for i := low(MyArray) to High(MyArray) do MyArray[i] :=<--- the debugger put me here with an exception - So I thought that High and Low both give back zero. How otherwise could I end up within the for loop when the array is empty? Actually the error already occured in the line before: High() gave back -1 but was assigned to a cardinal variable. With range check on I would have got an error here already. But with range check off it was simply assigned so that the high value now was a very high positive value! Therefore the for loop was entered although it should not do so. Under this impression, what kind of code should I have written? ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal