Recent

Author Topic: Unknown problem with a small code  (Read 7035 times)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Unknown problem with a small code
« Reply #15 on: February 16, 2018, 02:47:26 pm »
The result i got above is confusing. I understand the differences in results between using no modifier or using constref, but using const bails out for me for no apparent reason. Is there a differrence between using constref or the compiler doing that for us when it decides to pass a const by reference when using the const modifier ?
I seam to remember a discussion that said that for optimization reasons const parameters did not increase the reference count of a string while constref did, so yes a faulty reference count might result in a premature memory release but in most cases when the code is as tightly executed as this example it will not have time to corrupt the underline memory or at worst case it will "work once a while" instead of "failing once a while". I take it that the code fails 100% of the time? If yes it feels more like a buffer overflow than premature memory release.

if you do a simple change on the code eg
Code: Pascal  [Select][+][-]
  1. procedure TObjTest.NewSd(const path :String);
  2. var
  3.    Dum : string;
  4. begin
  5.   Dum := path;
  6.   Clear;
  7.   fPathSd:= path; //Copy(path,1,Length(path));
  8.   if fPathSd = '' then
  9.     sd:= TMemoryStream.Create
  10.   else
  11.     sd:= TFileStream.Create(fPathSd, fmCreate);
  12. end;
  13.  
you will see the error goes away which for me means that the problem is the reference counting. if I change it to
Code: Pascal  [Select][+][-]
  1. procedure TObjTest.NewSd(constref path :String);//changed to constref
  2. begin
  3.   Clear;
  4.   fPathSd:= path;
  5.   if fPathSd = '' then
  6.     sd:= TMemoryStream.Create
  7.   else
  8.     sd:= TFileStream.Create(fPathSd, fmCreate);
  9. end;
  10.  
something different happens although the application no longer raises any exceptions at the same time it does not preserve the data in the path parameter they get lost which drives me to think that constref is different but it does not increase the reference count of the string either, and I do not know how it differs.
« Last Edit: February 16, 2018, 03:28:36 pm 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

ASerge

  • Hero Member
  • *****
  • Posts: 2492
Re: Unknown problem with a small code
« Reply #16 on: February 17, 2018, 12:19:13 am »
Well, if my short explanations are not understood, I will explain in steps
First path:
Code: Pascal  [Select][+][-]
  1.  path:= BuildPath;
  2.  obj.NewSd(path);
  3.  
Code: Pascal  [Select][+][-]
  1. // at call "path" is pointer equal the BuildPath, or equal pointer of var "path" in TMyTest.Execute;
  2. procedure TObjTest.NewSd(const path: String = '');
  3. begin  
  4.  Clear; // this will clear fPathSd, so fPathSd = nil
  5.  fPathSd:= path; // this will copy pointer of "path" to fPathSd
  6.  if fPathSd = '' then
  7.   sd:= TMemoryStream.Create
  8.  else
  9.   sd:= TFileStream.Create(fPathSd, fmCreate);  // file created OK
  10.  

Second path:
Code: Pascal  [Select][+][-]
  1.  NewSd(fPathSd);
  2.  
Code: Pascal  [Select][+][-]
  1. // at call "path" is pointer equal the fPathSd with some value in heap
  2. // NO reference counting for "path", because is const
  3. procedure TObjTest.NewSd(const path: String = '');
  4. begin  
  5.  Clear; // this will clear fPathSd, so fPathSd = nil, reference to memory of previous fPathSd is zero, memory freed, pointer of "path" (it's copy of previous fPathSd) point to garbage!
  6.  fPathSd:= path; // this will copy pointer to garbage to fPathSd, so fPathSd also INVALID
  7.  if fPathSd = '' then // compare with garbage, in most cases not equal, goto else
  8.   sd:= TMemoryStream.Create
  9.  else
  10.   sd:= TFileStream.Create(fPathSd, fmCreate);  // in most cases bad, because heap changed at conversation of filename to system (point to garbage!) In my machine it empty line and '...error creating file ""...'
  11.  

If using constref, then also no refcount, but in this case is similar var path, so in line fPathSd:= path; no copy "bad pointer", but self to self, ie remains nil, so if fPathSd = '' then always true.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Unknown problem with a small code
« Reply #17 on: February 17, 2018, 06:58:34 am »
If using constref, then also no refcount, but in this case is similar var path, so in line fPathSd:= path; no copy "bad pointer", but self to self, ie remains nil, so if fPathSd = '' then always true.
so in the case of constref only a pointer to original string is passed instead of copying the string record. Then the const behavior seems like a bug to me. in any case that's interesting information. thank you.
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

Phoenix

  • Full Member
  • ***
  • Posts: 146
Re: Unknown problem with a small code
« Reply #18 on: February 17, 2018, 09:46:30 am »
Hello, thanks for all the explanations. The topic is very interesting!!  :)

Knowing the problem now I have eliminated it.  :D

Quote
Then the const behavior seems like a bug to me.
In this case I leave the post without the "solve"

Thank you all

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Unknown problem with a small code
« Reply #19 on: February 17, 2018, 10:58:58 am »
... the const behavior seems like a bug to me.

It is not a bug, but a stumbling block if you have not read the documentation, which is clear.
For instance,
"Note that specifying const is a contract between the programmer and the compiler. It is the programmer who tells the compiler that the contents of the const parameter will not be changed when the routine is executed, it is not the compiler who tells the programmer that the parameter will not be changed. This is particularly important and visible when using refcounted types. For such types, the (invisible) incrementing and decrementing of any reference count is omitted when const is used. Doing so often allows the compiler to omit invisible try/finally frames for these routines.
As a side effect, the following code will produce not the expected output:

  Var 
  S : String = ’Something’; 
 
Procedure DoIt(Const T : String); 
 
begin 
  S:=’Something else’; 
  Writeln(T); 
end; 
 
begin 
  DoIt(S); 
end.

Will write
 
   Something else

This behaviour is by design."

const is a hint to the compiler from the programmer, nothing more than that. Giving the compiler a false hint (as in this case) will most likely produce unexpected results. However, there are situations where giving a false hint to the compiler (declaring const, and then changing the const parameter) still "works".
« Last Edit: February 17, 2018, 11:06:34 am by howardpc »

BrunoK

  • Hero Member
  • *****
  • Posts: 766
  • Retired programmer
Re: Unknown problem with a small code
« Reply #20 on: February 17, 2018, 02:04:02 pm »
Will write
 
   Something else



1-Your code doesn't compile. Due to wrong quotes around literals.

This compiles :
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. Var
  4.   S : String = 'Something';
  5.  
  6. Procedure DoIt(Const T : String);
  7. begin
  8.   S:='Something else';
  9.   Writeln(T);
  10. end;
  11.  
  12. begin
  13.   DoIt(S);
  14.   ReadLn;
  15. end.
  16.  

2-But writes
  Something

It is probably lucky that it doesn't raise an error.

 

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Unknown problem with a small code
« Reply #21 on: February 17, 2018, 02:36:16 pm »
@taaaz:
thank you very much for your input. Really appreciated (and interesting read, especially with the addition from ASerge. thx ASerge).

@howardpc:
You see to have missed the/a point. I am aware of that documentation, and that is exactly what is bugging me.

The const parameter is either passed by value or passed by reference (compiler decides). Using const modifier delivers different result from using no modifier or constref modifier. Especially the latter i expected to work similar (in case the compiler decides to pass the const as reference). Instead using const  crashes for me while constref is producing expected result. Using no modifier also produces expected result, although different and both last methods follow the rules as expected) ).
« Last Edit: February 17, 2018, 02:39:25 pm by molly »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Unknown problem with a small code
« Reply #22 on: February 17, 2018, 02:43:10 pm »
The "compiler decides" scenario introduces uncertainty into the operation of const as a parameter modifier.

The example was quoted directly from the documentation which does not use ANSI characters for single quotes. I apologise that I did not realise the example had to be "interpreted" before it would compile.

BrunoK is right - the documentation gives the wrong output for its example (once you change it to be valid Pascal), so is misleading and confusing on this very point of the effect of combining "const" with a subsequent programmer change in the ref-counted parameter prior to its use.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Unknown problem with a small code
« Reply #23 on: February 17, 2018, 02:58:37 pm »
thank you howardpc.

In that case the only sane thing to advice to TS atm is to not do that  ;D

I find it tricky though as the string is copied locally so would have expected the reference count to increase, not leave us with something 'undetermined'. Perhaps it is as taaz described and depends on the situation. Sometimes it works as expected, sometimes it doesn't. Perhaps my writeln (instead of just passing the string to another function) is cause of my experienced crash. At least it does not work consistent for me.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Unknown problem with a small code
« Reply #24 on: February 17, 2018, 03:13:05 pm »
This behaviour is by design."
OK, my bad, the design is buggy then.
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

Nitorami

  • Hero Member
  • *****
  • Posts: 605
Re: Unknown problem with a small code
« Reply #25 on: February 17, 2018, 03:44:22 pm »
Quote
2-But writes
  Something

Whether the code prints "Something" or "Something else" is not random but depends on whether it is compiled with ansitrings ON or OFF.

BrunoK

  • Hero Member
  • *****
  • Posts: 766
  • Retired programmer
Re: Unknown problem with a small code
« Reply #26 on: February 17, 2018, 04:36:41 pm »
Quote
2-But writes
  Something

Whether the code prints "Something" or "Something else" is not random but depends on whether it is compiled with ansitrings ON or OFF.

I confirm with FPC 3.0.4 :
{$H-} // Output 'Something else'
{.$H+} // Output 'Something'


molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Unknown problem with a small code
« Reply #27 on: February 17, 2018, 04:59:37 pm »
I confirm with FPC 3.0.4 :
Me as well. So only when using ansistrings the const parameter shows different results from passing by variable or explicit by reference (constref). Not confusing or something like that  :)

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Unknown problem with a small code
« Reply #28 on: February 17, 2018, 05:23:43 pm »
For the avoidance of doubt:
with {$H+} (ansistrings) the output is "something"
with {$H-} (shortstrings) the output is "something else"

(I think BrunoK's last message has a typo).

 

TinyPortal © 2005-2018