Jump to content

Recommended Posts

I don't really understand the problem you adress in your topc. I'll give you a suggestion if you provide a proper example for your problem.

Share this post


Link to post
16 minutes ago, Attila Kovacs said:

if x(s, s) ....   and manipulating result on char basis for example

function x(const input: string; var output: string): boolean;
begin
  output := input;
  UniqueString(output);
  //...
end;

?

  • Like 2

Share this post


Link to post

The problem in this case is, that the output string can be the same string as the input is  "if x(s, s)", and depending on what x does, it can lead to unpredictable errors.

The question is rather how people are dealing with such functions, avoid this pattern totally, doesn't care, changing result with a parameter (which leads to another memory allocation), testing if input is the same as output on the beginning, etc...

Edited by Attila Kovacs

Share this post


Link to post

The way to deal with this is to have a function return a string whenever possible, that

way it is clear in the calling code that `S` is being overwritten.

Never output the same managed type of data that you allow as input in a var or out parameter.

 

function y(const input: string; out Success: boolean): string;
begin
  Result:= input + '1';
  //
end;

status:= x(S,S);    //Looks harmless
S:= y(S, status);   //The danger is clearly visible in the calling code

Alternatively he compiler could issue a warning when a const parameter is also passed as a var/out parameter.

 

also this code does not make a whole lot of sense:

 

if x(S,S) then ....
////^^^^^
////hiding dangerous -work- stuff with side-effects in an if statement.

You should never do unconditional work inside an if statement. That's too unexpected.

Edited by Johan Bontes
  • Like 2

Share this post


Link to post

@Johan Bontes if x() is just an example and not part of the problem. It could be xres := x(s,s).

And in your y() example I can't see any danger. Result is a separate string which will be copied /(or assigned its pointer?) to S at the end. Which means, the same performance or worse as omitting 'const' in my original post.

Edited by Attila Kovacs

Share this post


Link to post
1 hour ago, Attila Kovacs said:

It would be the same if I omit const for input, am I right?

Not quite. Delphi does not increase the reference count for const parameters. Therefore, this variant will be faster.

function x(const input: string; var output: string): boolean;
push ebp
mov ebp,esp
add esp,-$10
mov [ebp-$08],edx
mov [ebp-$04],eax
...

function x(input: string; var output: string): boolean;
... same commands ...
mov eax,[ebp-$04]
call @UStrAddRef
...

 

Share this post


Link to post

As a side note:

...
mov [ebp-$04],eax
mov eax,[ebp-$04]    // <--- ???
call @UStrAddRef
...

Compiler optimization is on. There is a place for optimizations. 😉 

  • Like 1

Share this post


Link to post
5 hours ago, Kryvich said:

As a side note:


...
mov [ebp-$04],eax
mov eax,[ebp-$04]    // <--- ???
call @UStrAddRef
...

Compiler optimization is on. There is a place for optimizations. 😉 

This shitty code has been generated for ages now. Don't think they will ever fix this.

Edited by Zacherl

Share this post


Link to post
18 hours ago, Attila Kovacs said:

@Johan Bontes if x() is just an example and not part of the problem. It could be xres := x(s,s).

And in your y() example I can't see any danger. Result is a separate string which will be copied /(or assigned its pointer?) to S at the end. Which means, the same performance or worse as omitting 'const' in my original post.

In that case can you please explain what the nature of your (time)bomb is? I thought it was the issue that the const input got changed by the proc, but that does not seem to be your problem.

  • Like 1

Share this post


Link to post
On 11/1/2018 at 3:52 PM, Kryvich said:

As a side note:


...
mov [ebp-$04],eax
mov eax,[ebp-$04]    // <--- ???
call @UStrAddRef
...

Compiler optimization is on. There is a place for optimizations. 😉 

I've seen such apparently useless constructs before. Not quite sure why they are there, but I was told (by those who can know) it may have something to do with debugging, although you can also find them in release code.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×