Jump to content
ertank

Local string variable value is not assigned for 2nd and following calls

Recommended Posts

Hello,

 

First of all, I am not experienced about technical details of variable initialization and such.

 

I am using Delphi 10.3.3 and targeting Win32 executable.

 

I am running multiple threads in my application. One of the threads is making rest web service calls. Other does SOAP web service calls. Below unit is only used by rest web service thread and that thread only.

 

Rest web service requires me to do logins for every 60 minutes. Problem appears at the second hour. Login requests sent as empty strings. I am sharing only relevant lines (timeout calculations, logging etc are not included below for simplicity):

unit MyRestUnit;

function Login(const AppKey, SecretKey: string): Boolean;

implementation

function Login(const AppKey, SecretKey: string): Boolean;
var
  Request: string;
  Response: string;
begin
  if AppKey.IsEmpty then Exit(False);
  if SecretKey.IsEmpty then Exit(False);

  Request := '{"appKey":"' + AppKey + '","secretKey":"' + SecretKey + '"}';
  if uUtils.Http.PostIndy(URL, Request, Response) then
  // Rest of the function code is irrelevant
end;

Code is just as in above. Request is filled in and HTTP request is made.

 

However, Request variable is filled in for the first time function is used. It is always becoming empty for the remaining calls. My log files says application is actually sending empty request bodies. Rest web service response error also confirms that. No garbage characters just empty.

 

If I use debug run (F9) and check variable value at run time. It holds proper value for first call, second and following calls it is always empty. Same problem exists for Release build and Debug build.

 

Only way I could make it always work is changing above code to something like below

Request := EmptyStr;
Request := '{"appKey":"' + AppKey + '","secretKey":"' + SecretKey + '"}';

I tried to use different local variable names (more than one) to rule out possible name collision and it still does not work for second calls to function, unless I first make it EmptyStr.

 

It is also interesting that I do not get any compile time hint/warning like "value assigned is not used" or similar for my second example above. I have all hints and warnings turned on in my project.

 

My internet searches did not result in something meaningful to me.

 

My question is: Why first example does not work for the second and following calls?

 

Asking in here because I could not find an explanation at all and I am really curious as to why. Moreover, that is the first time I am facing such a problem.

 

Thanks & Regards,

Ertan

Share this post


Link to post
var
  Request: string;
begin
  Request := '{"appKey":"' + AppKey + '","secretKey":"' + SecretKey + '"}';

 

Request is a local variable and the way you initialize it is perfectly correct. Each time Login() is called, you get a new variable (on the stack) which is initialized. If this doesn't work, then there is something elsewhere corrupting memory. That will be difficult to find. Especially for us which have no view on your code.

 

  • Like 1

Share this post


Link to post
5 hours ago, FPiette said:

Request is a local variable and the way you initialize it is perfectly correct. Each time Login() is called, you get a new variable (on the stack) which is initialized. If this doesn't work, then there is something elsewhere corrupting memory. That will be difficult to find. Especially for us which have no view on your code.

I do have FastMM4 full debug open and it does not report a leak. I do not know if it also reports for corruptions though. Are there any hints/suggestions to search for such corruptions?

Share this post


Link to post
25 minutes ago, Kryvich said:

Try remove const in the header of function Login.

That did not help.

Share this post


Link to post
26 minutes ago, ertank said:

I do have FastMM4 full debug open and it does not report a leak. I do not know if it also reports for corruptions though. Are there any hints/suggestions to search for such corruptions?

I use madExcept for that purpose. Be sure to select "crash instantly on buffer overflow" (or underflow).

 

Share this post


Link to post

I just installed and tried madExcept. It doesn't report any buffer overflow or underflow (tried both). Though, there are some leaks reported like Mutex Handle, TCriticalSection, TIdThreadSafe. First one is my code in DPR file, last two being in the initialization sections of relevant units. It was interesting to have leak report even FastMM4 is not reporting any.

 

Unfortunately, I failed to find a corruption using madExcept. I think is is harder to identify than I think it is.

 

Thanks.

Share this post


Link to post

Make a minimal reproduction. 

 

FastMM reports leaks only in the delphi heap. madExcept reports those leaks and also leaks in many other system resources. 

Share this post


Link to post

I guess inside the uUtils.Http.PostIndy() method, the Request parameter is somehow casted and associated with a buffer/indicator, which is later cleaned up by another part of the code (maybe thread?)

Share this post


Link to post

While trying to prepare minimal reproduction I realize that there is an "else" exists above some explanatory remark lines and my Request variable assignment comes next.

Turned out my mistake of leaving an else that should have been deleted at the first place.

if TokenExpireTime <> 0 then
begin
// some other stuff with begin..end blocks
end
else // problem source line


// some remark
// another remark
// more remark

Request := '{"appKey":"' + AppKey + '","secretKey":"' + SecretKey + '"}';

It turned out that Request is conditionally filled in if no line above.

Sorry about all the fuss and thanks to all.

 

Share this post


Link to post
5 minutes ago, ertank said:

It turned out that Request is conditionally filled in if no line above.

For that kind of bug, a step by step execution using the debugger make it obvious!

Share this post


Link to post

As usual the most simple explanation was the answer. If a string variable is empty then the obvious explanation is that you either assigned it to be empty, or didn't assign it at all. 

Share this post


Link to post
1 hour ago, ertank said:

Turned out my mistake of leaving an else that should have been deleted at the first place.

To avoid such hard-to-find mistakes, I use proper begin-end scopes ALWAYS   ......    ( and I really, really mean ALWAYS, all the time ).

 

That needs a lot of discipline over the years, that I dont always have.

 

<cross-fingers>

Since I did it that way, I never saw such failures again.

</cross-fingers>

 

Edited by Rollo62
  • Like 1

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

×