 My last video on how Ada really isn't as reliable as a lot of people think has gotten some attention and not really in the way that I Expected I actually expected to be getting quite a bit of flak and I've been getting some private messages from people who Agree with me It's been interesting One of them is on a guy who Not a guy Jesus one of them is with a guy who I sort of regularly corroborate with regularly talk to Him and I share pretty similar views in that overall is a good language Just certain things weren't really thought out and that they the the design of the language has just really stagnated because You can tell that the ARG just is Way too focused on it never Ever breaking anything even in the name of the goals of the language and despite I don't need to get into it Arguably with the last video You can say that I'm getting around the type system that I'm violating the type system and you can't expect any kind of safety in the language because of that well Actually, you you can still expect some safety and I'll get a little C sharp example at some point just to show how Even though you're violating parts of it and simply can't check for parts of what I did There are other parts that it can correctly handle but this one and This one is how I want to show I'm gonna show you how dangling Pointers are part of the design of the language Yeah, this is not a bug This is something that Originally was not allowed and got introduced into the language by design This would be fun We have Really simple demo program and the package that we'll cover is very simple as well But the idea here is just that we have a variable that I'm calling putter pointer It's just an access type to an integer now. I happen to be using an anonymous access Know that this does not matter And I'll switch it out so that you can see that fact This isn't a specific rule to anonymous access types. This just covers any access type whatsoever And we're assigning it the value of Whatever dangle is and what we'll get to that of course Now after that's done we'll go and put line so, you know writing to the console whatever the value is and And it's just an integer image with a dereference of this This as you can hopefully tell by the name creates a dangling pointer and I will show you that but Yeah, we'll get into here. I have a Non-anonymous access type the normal named access type Already defined just so that I can show you the switching around and how that doesn't matter And we have a an exposed function called dangle Now inside the body. There is a non-exposed a real private Because it is confusing about that inner that Is what actually creates the dangling pointer Although there needs to be a little setup so what we are specifically doing is creating a pointer that references this and it escapes this scope which You would think it's not supposed to be able to do You could return the value of this just fine and because it's a No, Ida doesn't do value and reference types exactly the rules for that are actually Way more complicated than I think they should be and there are benefits to not handling that automatically Depending on certain weird things. I really don't think it should do that Like part of me likes it but then oh There's so many weird rules that you have to keep track of if it's handled for you instead And it's just easier to have it obvious But you could just copy the 42 when it's returned and then you you know, but we're creating an actual access to that which means we have a reference to that and There analyze the problem But let me show you real quick that we're not just simply well actually let me run this And I've already built this so let's just run that and oh well I Intended to show you just the single line and then whatever but you can clearly see that No, you can't because you saw the old code and you don't know if I'm changing things to does a sleight of hand Let me rebuild this Yeah, so we have this with the single line and run it you see we get the 42 that we expect Nothing odd there this well It's not that odd you could you know where the 42 came from some of you who know the language well are just Screaming in your heads right now based on what you saw So let me run this again, and you can see that it's 42, but then is suddenly zero So clearly something is going on because this is the exact same call It's the exact same variable everything is exactly the same, but suddenly it's not the same value and When you see those kinds of things it's always one of two things one is a Concurrency problem where a value is being changed Different times You're able to diagnose that by running it over and over and over again and looking for those changes But considering we're not using any concurrency features it Literally has to be the other one, which is when you have a dangling pointer Let me show you what let's walk through the code first Just to get an idea of how this happens and I'll show how it does have some safeguards that again is Leads to people thinking that this is safer than it really is and feel good about the code, but Look I have 13 lines on screen that implement a dangling pointer Come on, so we were on the code We have a call to dangler Dangler Initializes this value It's an integer assigned 42, and it is aliased all alias to means and Ida is that You want to be able to get the memory address of that value It doesn't change any of the semantics otherwise. It just ensures That you can get a memory address for that value If that seems a little weird It is because in most languages you can just always get the memory address there are This is actually something added as well and makes a lot of sense. There are advantages to not letting you get memory addresses and there are some There are advantages to Optimizations of things that you can do Safety checks and whatnot that are possible when you can guarantee that they will never need the address of it and by Explicitly saying you need to be able to take the address of something. It's just one of those nice opt-in things It's very Similar concept to how functional programmers advocate for things being immutable by default and you having to opt into them being mutable There are advantages to it being immutable Same kind of idea But then after that's assigned we have a call to Inner and we pass the value into inner Yeah, hold up We have a call to enter and we pass the value into inner and then whatever this evaluates to we directly return So now for inner We're just passing at the value and it's an input output. I'm not sure if this is important I haven't played around with that part um And then we would just return the integer access Um And then literally all we do Inside of this it's just return the the access to it What this does for those unfamiliar is just The referencing Uh, if you're familiar with the C's family of languages, it's just the little star before it that's it's it's just I had a syntax for that um Why people feel quite a bit safer normally is that if you Just do this and then go to build it That shouldn't be Oh, because I didn't save it. Yeah, you can see and this is the correct thing that I should say There's a non-local pointer cannot point to the local object Uh, and that's because you have a clear situation of the the the pointer to this winds up going to the scope above it Uh, and pointing to something inside of the function, which is clearly invalid um And this function is what allows us to get around it even though this function is literally just doing the same thing so Even though it's literally Doing the same thing Let me actually phrase that ever so slightly differently Because it is literally doing the same thing That means this is not a bug This is not some kind of code exploit This has to do with the language rule now Before we get into the language rule, let me show how this is not something specific To named access types or anonymous access types or anything like that So we return an access integer and just Let me uh Calls to dangle me and be ambiguous not Oh, uh, that's because I need to change this one as well And you can see same thing And just the same you can change it here and it's not going to matter And we can change it here and it's not going to matter Then we got another one because I forgot to change it and I'm gonna roll and you can see the same thing Um, yeah dangling pointer Uh, as for why this is zero this call Um, just so I can explain this real quick Based on the way the Um All of this is resolved You wind up There's a stack frame created when this is called There's another stack frame created when this is called After this is called so like Basically right before this is returned this stack frame is going to be torn down This gets returned Let me go over to here where this happens. So right after this Uh This stack frame is torn down Now at the time nothing replaces where this stack frame was So The memory is still there Uh, nothing supposed to be using it but everything All of the values that were written to memory there are still there and part of that stack frame is going to be Uh, this this value because this value Uh wound up being Returned Um, actually no not because of that it it it winds up being there regardless Uh, but the thing is As we immediately have another Uh Stack frame that winds up being Created and disposed and whatnot and basically as part of that You wind up For whatever reason at that specific memory address a zero was written um Now on your machine depending on exactly what else you've got going on and uh, how your operating system handles Um This kind of stuff you may get a different value there Uh, I happened to get zero but the The idea is that you're getting a different value because that spot in memory is being overwritten Uh, which is a clear indicator of a dangling pointer so I keep saying that there's a specific rule about that that allows this Uh, that this is a defect in the language itself not in the compiler i'm using or anything like that And the reason why I say that is the specific rule is located in this part of the reference manual Now some of you may recognize Where we are 3.10.2 the operations of access types Despite some of the bullshit that's said about this It's really not that hard to understand about 95 of the rules say the exact same kind of thing just About a different thing um The overwhelming majority of it Exactly the same basically Um I think a big reason why it gets the reputation that it does is something that is really hard to understand that there are only a Few people in the world that understand it has to do with how There are a lot of rules. So it is very overwhelming. It is very um visually overwhelming it's Visually a lot of information to go through to find the specific thing you are looking for and that makes it kind of intimidating um And also it appears so early on in the add a reference manual So because of that a lot of people who really aren't super familiar with the language are looking at that trying to um Understand parts of the language and this really is not something you need to understand early on Uh, this really isn't even something you need to understand unless you're like really deep in the language um Trying to do some funky stuff or are implementing a compiler or something like that Uh This don't need to cover because they're so new and this is so early in the reference manual They stumble upon it and are completely overwhelmed by what is being talked about But the specific rule is down here 10.1 slash three Um Well, actually pretty much the entire 10 saying uh, not not 10 for but past this point There are little bits here and there that affected but the this is the big one um The accessibility level of the result of a function call is that of the master of the function call So that is The thing that is result the thing that is the result of a function call. So whatever the function call returns Has to be the same accessibility level of whatever is calling that function That is how we were able to escape Um, which you would think were the the rules around the access type Uh, that is why it was caught In what I showed you was the reasonable thing to do Um, but was it easily very easily escaped with the call to enter That's why I said the call to enter was what really allowed this um But it is it is dependent on two function calls. You cannot pull this off without the two function calls um This approach uh, there is something I got to look into involving possible dangling pointers with Uh An access to a subroutine as well as to the internals of a record Neither of those are caused by this rule And I'm not sure whether those other things are bugs or not Uh, like I said, I haven't looked into them Um, but no, this is something that is actually Allowed by the language You have a designed in dangling pointer Feeling good about the reliability of it yet