Swift property loaded in memory before initialisation is called - swift

In my app it looks like the property is loaded in memory before it's even called. Either there's something wrong with my understanding, or there's something I've overlooked. To illustrate that I've put a breakpoint soon after signIn is tapped as you can see on the image (line 226):
I'm expecting to initialise a property let user = User() on line 230. So I have no idea how could user be already loaded in memory, as seen on the bottom left of the attached image.
Why does this happen?
Is this some kind of code optimisation that happens under the hood?
I can confirm that user has not been loaded / initialised prior to that (it's not a class property). Additionally I can confirm that commenting out line 230 and below results in user not being loaded, so it looks that line 230 is the cause for user being loaded. But the strange thing is that this happens before it's called, as I've paused the execution on line 226 with a breakpoint.

It's important to be able to read the variables list. All local variables are always shown, even if they have not been initialized yet, because the storage has already been set aside for them. Before initialization, therefore, the variable is shown, but its value may be bogus. My guess is that the value is bogus. It says it's a User because that is its type, but at the time you are looking, it is pointing at garbage, and you should ignore it. After the execution path passes thru the initialization, the value will change and will be the real value.
(However, if this is a Release build, then there might indeed be optimization of some sort, because this is a constant whose value does not depend upon preceding code, so it can be allocated at any time. But you should not be debugging a Release build.)

It hasn't been loaded into memory. The debugger sees the variable in scope and displays it but the number it's showing is whatever is lying around in memory. If you step past your let user... statement, you should see the value of the variable change to something more like the other object addresses in your picture.

Related

breakpoint with debugger Commend jump in xcode

I made a breakpoint in Xcode with the jump commend to force passing some condition, but when it execute to line 168 it crash with message
"Thread 1: EXC_BAD_ACCESS (code=1, address=0x1)"
why did that happen?
the console logged:
warning: MoreMultitypeCollectionViewCell.swift:178 appears multiple times in this function, selecting the first location:
MoreMultitypeCollectionViewCell.(updateButtonStateCkeck in _9A12557DCAB30EEB52DC7C2EA09487CD)() -> () + 1580 at MoreMultitypeCollectionViewCell.swift:178
MoreMultitypeCollectionViewCell.(updateButtonStateCkeck in _9A12557DCAB30EEB52DC7C2EA09487CD)() -> () + 1600 at MoreMultitypeCollectionViewCell.swift:178
my questions are:
How should I type in lldb to select location?
Is there a better way to force passing into If Statement without change code and rebuild project?
sometimes when I type 'po' in lldb or click print description in variable view, it will show fail message, how is that?
1) In lldb, the equivalent command is thread jump and you can specify an address as well as a line number there.
2) thread jump or the Xcode equivalent is an inherently dangerous operation. If you jump over the initialization of some variable, you will be dealing with bad data now and will likely crash. That sort of thing you can sometimes spot by eye - though Swift is lazy about initialization so the actual initialization of a variable may not happen where you think it does in the source. There are more subtle problems as well. For instance, if you jump over some code that as a byproduct of its operation retains or releases an object, the object will end up under or over retained. The former will cause crashes, the latter memory leaks. These retains & releases are generated by the compiler, so you can't see them in your source code, though you could if you look at the disassembly of the code you are jumping over.
Without looking at the code in question, I can't tell why this particular jump caused a crash.
But you can't 100% safely skip some of the code the compiler choose to emit. Looking at the disassembly you might be able to spot either (a) a better place to stop before the jump - i.e. stop past some retain or release that is causing a problem or jump to an address in the middle of a line so you still call a retain that's needed. You'll have to figure this out by hand.
3) There's not enough info to answer this question.
BTW, your image links don't seem to resolve.

"Initialisation of immutable value'context' was never used, consider replacing assignment to '_' or removing it

In swift I declared a variable as
let context:LAContext = LAContext()
It throws a warning
"Initialisation of immutable value'context' was never used, consider replacing assignment to '_' or removing it.
It's all in the error message
value...was never used
Your variable isn't being used anywhere, so Xcode tells you that you can remove it (because having unused variables is a waste of memory). Just use your variable somewhere and the error will go away (e.g. get a value from it, print it, etc).
Of course you mean to use it somewhere right? Otherwise you wouldn't have declared it. It's just that the Xcode (especially the new one, I noticed) checks for errors immediately, so these kinds of errors appear before you can really do anything about it.
Edit: I didn't imagine that almost 7 years later people would still be commenting on a post regarding a beginner-level compiler warning, but to be more specific, yes there are some cases where you might not want to keep a variable around or where you want to discard some return value, so you don't necessarily always "mean to use it somewhere". See comments for more.

Why small changes make "Access violation at address xxx" error on this delphi code?

I have 2 pieces of code :
It works normal
with ADOTemp do
begin
SQL.Clear;
SQL.Add('INSERT INTO documents');
SQL.Add('(document_date,fk_id_status,money_direction,');
SQL.Add('paid,addition,saving,fk_id_base,fk_id_user)');
SQL.Add('VALUES ');
SQL.Add('(CONVERT(DATE,GETDATE(),103),:pfk_id_status,:pmoney_direction,');
SQL.Add('0,0,0,'+IntToStr(p_id_base)+',:pfk_id_user)');
Parameters.ParamByName('pfk_id_status').Value := p_id_status;
Parameters.ParamByName('pmoney_direction').Value := p_money_direction;
// Parameters.ParamByName('p').Value := p_id_base;
Parameters.ParamByName('pfk_id_user').Value := fMain.ApplicationVariablers.user_id;
ExecSQL;
end;
It does not work and returns a terrible error
with ADOTemp do
begin
SQL.Clear;
SQL.Add('INSERT INTO documents');
SQL.Add('(document_date,fk_id_status,money_direction,');
SQL.Add('paid,addition,saving,fk_id_base,fk_id_user)');
SQL.Add('VALUES ');
SQL.Add('(CONVERT(DATE,GETDATE(),103),:pfk_id_status,:pmoney_direction,');
SQL.Add('0,0,0,:p,:pfk_id_user)');
Parameters.ParamByName('pfk_id_status').Value := p_id_status;
Parameters.ParamByName('pmoney_direction').Value := p_money_direction;
Parameters.ParamByName('p').Value := p_id_base;
Parameters.ParamByName('pfk_id_user').Value := fMain.ApplicationVariablers.user_id;
ExecSQL;
end;
Error on image, line 1917
It seems that this question is in reference to your earlier question: Delphi, error :"Access violation at address xxxxxxxx. Read of address yyyyyyyy", at AdoQuery.SQL.Text:='''
You had added and accepted an answer there along the lines seen in this question. The error message, an AV in msvcrt.dll is indicative of a serious programming error. Perhaps a heap corruption. Perhaps something else. The change you made that stops the error occurring does not really fix the problem. The problem will still be there, lying dormant. You just got (un)lucky that the change you made appeared to fix the problem.
Access violations are not always reproducible. That's just their nature. When you encounter one you need to understand why it happens. Simply using trial and error to re-organise code from a completely different location will never lead to the real solution.
What you should be doing is tracking down the real cause of the problem. Do that, fix it, and either version of the code above will work. This is probably not the answer you are wanting to get. You may very well not want to accept what I say. But, speaking from experience, until you recognise that you have a more serious problem, you will make no headway here.
Looking at your code in the bitmap...I'm pretty sure you access violation is because of what David just said...you have serious Memory problems in your code...Your not freeing your objects...that you are creating...Anytime you pass a nil reference to Owner in a TComponent Constructor...your telling the compiler...that you know what your doing and will free it when your finished with it...Matter of fact good practice is to always free objects that you declare and use exclusively in the scope of your method.
procedure TForm1.MyMethod;
var
a_MyComp: TMyComp;
begin
a_MyComp := TMyComp.Create(nil);
Try
//use my a_MyComp...
Finally
a_MyComp.Free;
End;
end;
Check out your code in CreateNewDocument...you'll notice that your not freeing your AdoTemp.
-Rick
Access violation exceptions (AVs) tell you that you have made a mistake in the memory access of your program. However, the way access violations work: they are unable to guarantee always detecting the error every time you make a mistake. (Sometimes you get un-lucky and no access violations are raised, but the mistake is still there causing other things to quietly go wrong inside your application.)
You can think of the memory available to your program being represented as below (where "." means the memory is not allocated to anything, and "A" means the memory is allocated to something within your program: e.g. object, local variable, parameter, machine code).
[.......AAA..AAAA.....AA......A...A...........AAA....A.......AA.........AAAAA]
Suppose you create some object; this will require memory to be allocated for the object itself. If the object in turn creates child objects, this will also be allocated in memory. (I'll use "O" and "C")
/-ref--\
[.......AAA..AAAAO....AAC.....A...A.....C.....AAA....A.......AA.........AAAAA]
\-ref------------------/
Note that within the memory allocated to O, it might hold references to its child objects.
Conversely to the above, whenever an object is destroyed, its memory is deallocated. Let us suppose you have made a mistake in your memory access, and something has destroyed one of O's child objects before O has finished using it.
/-ref--\
[.......AAA..AAAAO....AAC.....A...A...........AAA....A.......AA.........AAAAA]
\-ref------------------/
If O now tries to use its second child object, you will get an access violation. However, you might be un-lucky and not get an access violation showing your earlier mistake IF:
You destroy O without it trying to do anything to the second child object.
Or you first create a new object that happens to be allocated in the exact same place the child object was.
The second situation tends to be worse than the first, because every time C2 is used on the assumption that it is the correct child of O: unexpected results are produced and an incorrect values are written in memory. These incorrect values may be important data, or references to other objects (making the problem get worse over time).
So: Whenever yo do get an access violation, thank your lucky stars and hunt down the root cause of the problem.
NB! NB! I cannot stress the importance of the above enough.
Investigating your particular problem
First note, when an exception pauses in the debugger, the code usually points to the next line that would have been executed if not for the exception. (This doesn't affect anything here, because the previous line is also ADOTemp.SQL.Add; - the point is be prepared to consider the previous line as the cause of an exception - and test to confirm it!)
Useful tip: When an exception is thrown within Delphi/Third Party code, it can be useful to build with Debug DCU's or recompile Third Party source with debug information to get closer to the actual line raising the exception. (This can even be useful in situations like this where the error appears to be inside a Microsoft DLL.)
Looking at your screen-shot, the exception is thrown from a brand new instance of TADOQuery. Now there really isn't any sensible explanation for a brand new query to be throwing access violations when simply adding text to its SQL query. This strongly implies a corruption problem as described earlier.
One possibility would be another thread interfering with this one. (NOTE: even if your application isn't multi-threaded, the ADO objects do have built-in support for asynchronous operations.) However, I'm going to ignore that possibility for now because threading issues tend to be less consistent than you've implied this one is.
So, assuming you have a memory access problem somewhere else that is only manifesting here with a brand new TADOQuery (used correctly at least up to the point of the AV) - what other objects are interacting with this query to possibly cause corruption?
ADOTemp.Connection := fMain.ADOConnection;
There is a very strong possibility that commenting out the above line would also eliminate your access violation. So what are the possible problems:
fMain might have been destroyed prematurely and is now a dangling pointer meaning the code to return ADOConnection could do any of a number of unexpected things.
Any of the code backing fMain.ADOConnection may be referencing corrupted memory or dangling pointers; this includes the returned connection itself.
NOTE: One very common cause of invalid memory access is to have a function such as GetADOConnection that does not correctly initialise its Result. So in some cases it returns a 'random' address in memory, resulting in all sorts of unexpected behaviour when something tries to use the connection.
Is your ADOConnection created on a different thread, and being used by multiple threads?
PS: Don't forget to follow Rick's advice, and make sure you destroy the query when you've finished using it. Who knows, there might be an internal bug in ADO that when it runs out of a particular internal resource (due to queries not being destroyed), that causes ADO to start throwing AVs.
NOTE: You should be able to test my theory without altering functionality by simply changing the ADOTemp.Connection := ... line. Simply assign a connection string to the query instead of a connection object. However, if that solves (or more correctly stated: hides) the problem, please follow my advice, and hunt down the root cause of the AV.

Using Option/Maybe to represent uninitialised variables that are initialised asynchronously

There is a pattern in a codebase I'm working on where var x: Option[A] = None is used for variables which start uninitialised, and are populated at some point after the program starts, either with asynchronously loaded data, or in response to the very first event of some kind occurring.
After this point, the variable is always of type Some - the None part is only ever used at the start of the program.
Whilst this models what's going on quite well (the last event I saw is None when the program starts, and for ever after that it's Some(event)), I feel like I'm paying the price for using an option every time I interact with one of these variables, even though I only actually make use of it once.
It seems I was unclear - the value within Some can change, hence the var. I can't just use a future to await initialisation and go from there.
Is there a cleaner way to represent this delayed initialisation?

On iOS, the if() statement has different result between release version and debug version

I have an app submitted to Apple Store, and it passed. But I found there was a bug will make the app crash. Finally, I found the real problem is a snap of code has the opposite result.
code:
CGPoint now;
CGPoint old;
UIView *lastDot;
now = dotView.center;
if(lastDot){
//release version, will go here. then crashed.
old = lastDot.center;
}else{
//debug version, will go here. run ok.
}
I declare a UIView pointer, and check it with "if statement",
UIView *lastDot;
the debug version consider the lastDot as nil, but the release version think is not null.
can anyone give me any idea? thank you.
Depending on your compiler settings, debug builds usually initialize pointers to some sentinel values like 0xcccccccc.
UIView *lastDot = nil;
Should work as expected.
The issue is due to uninitialized pointer.
Initialize it to nil for avoiding such troubles.
UIView *lastDot = nil;
I know you already got the answer.
I just want to add some points too:
Pointers are just like any other variable: if you don't explicitly set
them to a value, the value will be undefined means a random value. If
you then accidentally access the variable, very bad things can happen.
Sometimes people recommend that pointers be assigned to NULL, the
universal value meaning "this pointer doesn't point at anything",
because a lot of code already checks for NULL pointers. For example,
if you call [nil release], it's guaranteed to do nothing. If you
passed an uninitialized pointer in who knows what would happen.
It's really just a safeguard against programmer error. If you
initialize pointers to a reasonable value, it's less likely that an
uninitialized pointer will cause a system crash sometime in the
future.
When you don't initialize a pointer and then try to use it, you have 3
problems:
It might be pointing at memory you don't have access to, in which case it causes a segmentation fault and crashes your program
It might be pointing at real data, and if you don't know what it's pointing to, you're causing unpredictable (and very hard to debug)
changes to your data.
You have no way of knowing if it's been initialized or not - because how do you tell the difference between a valid address and the address
that happened to be there when you declared the pointer?
Initializing every pointer to nil seriously decreases or eliminates
those problems:
If I try and use it, it will still segfault, but at least I can test if it's NULL and act accordingly - I can know that it WILL segfault,
and do something else. If it's a random value, I don't know anything
until it crashes.
If you initialize it to nil, I can't make it point to data unless I explicitly tell it to. So I only modify what I meant to.
As implied above, I can tell when I've initialized it and when I haven't, and make a decision.
Obviously it's a matter of style, and it is possible to write an
application where variables are only initialized to their intended
value, but I feel it is safer and easier to initialize them to nil
always. Even the best programmers make typos - nil makes it easier
to know when that's happened.
Reference :
eskimo
Initializing pointers always necessary