www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - stack frame & dangling pointer weirdness

reply Alain De Vos <devosalain ymail.com> writes:
Following program:
```
import std.stdio;

void main()  trusted
{

int *p=null;
void myfun(){
	int x=2;
	p=&x;
	writeln(p);
	writeln(x);
}
myfun();
*p=16;
writeln(p);
writeln(*p);
}
```

outputs :
7FFFFFFFDFAC
2
7FFFFFFFDFAC
32767

I don't understand why. Would it be possible to explain  ?
Apr 20 2022
next sibling parent ag0aep6g <anonymous example.com> writes:
On 21.04.22 07:49, Alain De Vos wrote:
 int *p=null;
 void myfun(){
      int x=2;
      p=&x;
      writeln(p);
      writeln(x);
 }
 myfun();
 *p=16;
 writeln(p);
 writeln(*p);
`p` is no longer valid after `myfun` returns. Dereferencing it is an error. The two `writeln` calls in `main` re-use the memory that `p` points to for their own purposes.
Apr 20 2022
prev sibling next sibling parent max haughton <maxhaton gmail.com> writes:
On Thursday, 21 April 2022 at 05:49:12 UTC, Alain De Vos wrote:
 Following program:
 ```
 import std.stdio;

 void main()  trusted
 {

 int *p=null;
 void myfun(){
 	int x=2;
 	p=&x;
 	writeln(p);
 	writeln(x);
 }
 myfun();
 *p=16;
 writeln(p);
 writeln(*p);
 }
 ```

 outputs :
 7FFFFFFFDFAC
 2
 7FFFFFFFDFAC
 32767

 I don't understand why. Would it be possible to explain  ?
When you pass a pointer to writeln conceptually it gets copied, the address that is, but the memory the address points to is in no man's land because it was in an old stack frame. As such, this memory gets "overwritten" (at this point it's invalid anyway) when you call writeln, so when you dereference it you get something from the old stack of writeln rather than 16.
Apr 20 2022
prev sibling next sibling parent bauss <jj_1337 live.dk> writes:
On Thursday, 21 April 2022 at 05:49:12 UTC, Alain De Vos wrote:
 Following program:
 ```
 import std.stdio;

 void main()  trusted
 {

 int *p=null;
 void myfun(){
 	int x=2;
 	p=&x;
 	writeln(p);
 	writeln(x);
 }
 myfun();
 *p=16;
 writeln(p);
 writeln(*p);
 }
 ```

 outputs :
 7FFFFFFFDFAC
 2
 7FFFFFFFDFAC
 32767

 I don't understand why. Would it be possible to explain  ?
See my comment for some ELI5 of what's going on. Of course it's a bit more complicated than that, but I hope it gets the point across. ``` void main() trusted { int *p=null; // P is null obviously void myfun(){ int x=2; p=&x; // Sets the address of p to the address of x, which is on the stack of myfun writeln(p); // Writes the address of p writeln(x); // Writes the value of x (same as value of p) } myfun(); // We call myfun // Any memory that was in the stack of myfun is invalid here, returning to the stack of main. *p=16; // Sets the value of p to 16, but p points to the address of an invalid memory location, since x was on the stack within myfun and thus isn't valid outside of myfun writeln(p); // Writes the address of p, which is the same since the address of p was stored on the stack of main writeln(*p); // Attempts to write the value of p, which points to an "invalid" memory address, or at least it's now something completely different than it was before, considering the stack of myfun is gone, so it writes out a garbage value } ```
Apr 20 2022
prev sibling parent reply drug <drug2004 bk.ru> writes:
On 21.04.2022 08:49, Alain De Vos wrote:
 Following program:
 ```
 import std.stdio;
 
 void main()  trusted
 {
 
 int *p=null;
 void myfun(){
      int x=2;
      p=&x;
      writeln(p);
      writeln(x);
 }
 myfun();
 *p=16;
 writeln(p);
 writeln(*p);
 }
 ```
 
 outputs :
 7FFFFFFFDFAC
 2
 7FFFFFFFDFAC
 32767
 
 I don't understand why. Would it be possible to explain  ?
Like others have said `writeln` overwrites the memory. You can check it by commenting `writeln(p);` out - then you get: ```d 7FFF23725D1C 2 16 ```
Apr 20 2022
parent reply Alain De Vos <devosalain ymail.com> writes:
On Thursday, 21 April 2022 at 06:57:41 UTC, drug wrote:
 On 21.04.2022 08:49, Alain De Vos wrote:
 Following program:
 ```
 import std.stdio;
 
 void main()  trusted
 {
 
 int *p=null;
 void myfun(){
      int x=2;
      p=&x;
      writeln(p);
      writeln(x);
 }
 myfun();
 *p=16;
 writeln(p);
 writeln(*p);
 }
 ```
 
 outputs :
 7FFFFFFFDFAC
 2
 7FFFFFFFDFAC
 32767
 
 I don't understand why. Would it be possible to explain  ?
Like others have said `writeln` overwrites the memory. You can check it by commenting `writeln(p);` out - then you get: ```d 7FFF23725D1C 2 16 ```
No error was thrown during execution. Should an error be thrown or is this optional by the operating system ? How can i force an error to be thrown when doing something "bad" ?
Apr 21 2022
next sibling parent ag0aep6g <anonymous example.com> writes:
On 21.04.22 13:25, Alain De Vos wrote:
 How can i force an error to be thrown when doing something "bad" ?
Use safe.
Apr 21 2022
prev sibling next sibling parent drug <drug2004 bk.ru> writes:
On 21.04.2022 14:25, Alain De Vos wrote:
 
 No error was thrown during execution.
 Should an error be thrown or is this optional by the operating system ?
 How can i force an error to be thrown when doing something "bad" ?
No error may be thrown here because it is not an error at all - compiler thinks you do it intentionally because D is a system programming language and your code is a trusted one. To get compilation error you should use safe - but this may limit you in some way (not like in rust but nevertheless). In runtime you can also use valgrind (linux only).
Apr 21 2022
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Apr 21, 2022 at 11:25:29AM +0000, Alain De Vos via Digitalmars-d-learn
wrote:
 On Thursday, 21 April 2022 at 06:57:41 UTC, drug wrote:
 On 21.04.2022 08:49, Alain De Vos wrote:
 Following program:
 ```
 import std.stdio;
 
 void main()  trusted
 {
[...]
 }
 ```
[...]
 How can i force an error to be thrown when doing something "bad" ?
Use safe instead of trusted. T -- No! I'm not in denial!
Apr 21 2022