Results 1 to 10 of 10

Thread: auto variables not deallocating memory ???? Share/Save - My123World.Com!

  1. #1

    auto variables not deallocating memory ????

    today i studied about auto variables in c++ and prepared a program of it ..
    In that programme , i have stored the memory address of the auto variable in a global pointer and after the execution of the function when i checked the value of the auto variable through the pointer in which i have stored its memory address .. it still shows the same value which i have assigned to it within its function ..
    is it not deallocating the memory or there is something else because of which it is happening ??
    And the main thing is that, it is only showing the same value just after the calling of the function .. and when i again print the value of that auto variable then it shows some garbage value ..




    Code:
    #include<iostream>
    using namespace std;
    
    int *p;
    
    void check()
    {
            auto int a=88;
            p=&a;
    }
    
    
    int main()
    {
    
            check();
            cout<<"value is :"<<*p<<endl;
            cout<<"value is :"<<*p<<endl;
            return 0;
    }

    #####################
    output of the programme
    #####################

    Code:
    value is :88
    value is :32535

  2. #2
    Security Researcher fb1h2s's Avatar
    Join Date
    Jul 2010
    Location
    India
    Posts
    616
    Blog Entries
    32
    Nice stuffs you'r digging on , let me add up ur confusion , and keep this thread up for some time so that more people dig into these issues and have some quality discussion.

    Auto Variable Hint [wiki]:

    In C++, the constructor of automatic variables is called when the execution reaches the place of declaration. The destructor is called when it reaches the end of the given program block (program blocks are surrounded by curly brackets).


    g++ -Wall test.cpp -o test

    PHP Code:
    #include<iostream>
    using namespace std;
    int *p;
    void check()
    {
    auto int a=34;
    p=&a;
    cout<<"value is:"<<*p<<endl;
    cout<<"value is:"<<&p<<endl;
    }
    int main()

    {
    check();

    cout<<"value is:"<<*p<<endl;
    cout<<"value is:"<<&p<<endl;
    cout<<"valueq is:"<<*p<<endl;
    return 
    0;


    Output:


    value is:34
    value is:0x804a0d4
    value is:34
    value is:0x804a0d4
    valueq is:34

    PHP Code:
    #include<iostream>
    using namespace std;
    int *p;
    void check()
    {
    auto int a=34;value is:34
    valueq is
    :-1217201928
    p
    =&a;
    cout<<"value is:"<<*p<<endl;

    }
    int main()

    {
    check();

    cout<<"value is:"<<*p<<endl;
    cout<<"valueq is:"<<*p<<endl;
    return 
    0;


    Output:
    value is:34
    value is:34
    valueq is:34

    Disassemble:

    Breakpoint 1, 0x0804876a in main ()
    (gdb) disassemble
    Dump of assembler code for function main:
    0x08048767 <+0>: push %ebp
    0x08048768 <+1>: mov %esp,%ebp
    => 0x0804876a <+3>: and $0xfffffff0,%esp
    0x0804876d <+6>: push %ebx
    0x0804876e <+7>: sub $0x1c,%esp
    0x08048771 <+10>: call 0x8048714 <_Z5checkv>
    0x08048776 <+15>: mov 0x804a0d4,%eax
    0x0804877b <+20>: mov (%eax),%ebx
    0x0804877d <+22>: movl $0x8048910,0x4(%esp)
    0x08048785 <+30>: movl $0x804a040,(%esp)
    0x0804878c <+37>: call 0x8048618 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_E S5_PKc@plt>
    0x08048791 <+42>: mov %ebx,0x4(%esp)
    0x08048795 <+46>: mov %eax,(%esp)
    0x08048798 <+49>: call 0x80485b8 <_ZNSolsEi@plt>
    0x0804879d <+54>: movl $0x8048638,0x4(%esp)
    0x080487a5 <+62>: mov %eax,(%esp)
    0x080487a8 <+65>: call 0x8048628 <_ZNSolsEPFRSoS_E@plt>
    0x080487ad <+70>: mov 0x804a0d4,%eax
    0x080487b2 <+75>: mov (%eax),%ebx
    ---Type <return> to continue, or q <return> to quit---
    0x080487b4 <+77>: movl $0x804891a,0x4(%esp)
    0x080487bc <+85>: movl $0x804a040,(%esp)
    0x080487c3 <+92>: call 0x8048618 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_E S5_PKc@plt>
    0x080487c8 <+97>: mov %ebx,0x4(%esp)
    0x080487cc <+101>: mov %eax,(%esp)
    0x080487cf <+104>: call 0x80485b8 <_ZNSolsEi@plt>
    0x080487d4 <+109>: movl $0x8048638,0x4(%esp)
    0x080487dc <+117>: mov %eax,(%esp)
    0x080487df <+120>: call 0x8048628 <_ZNSolsEPFRSoS_E@plt>
    0x080487e4 <+125>: mov $0x0,%eax
    0x080487e9 <+130>: add $0x1c,%esp
    0x080487ec <+133>: pop %ebx
    0x080487ed <+134>: mov %ebp,%esp
    0x080487ef <+136>: pop %ebp
    0x080487f0 <+137>: ret

    Breakpoint 2, 0x08048718 in check() ()
    (gdb) disassemble
    Dump of assembler code for function _Z5checkv:
    0x08048714 <+0>: push %ebp
    0x08048715 <+1>: mov %esp,%ebp
    0x08048717 <+3>: push %ebx
    => 0x08048718 <+4>: sub $0x24,%esp
    0x0804871b <+7>: movl $0x22,-0xc(%ebp)
    0x08048722 <+14>: lea -0xc(%ebp),%eax
    0x08048725 <+17>: mov %eax,0x804a0d4
    0x0804872a <+22>: mov 0x804a0d4,%eax
    0x0804872f <+27>: mov (%eax),%ebx
    0x08048731 <+29>: movl $0x8048910,0x4(%esp)
    0x08048739 <+37>: movl $0x804a040,(%esp)
    0x08048740 <+44>: call 0x8048618 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_E S5_PKc@plt>
    0x08048745 <+49>: mov %ebx,0x4(%esp)
    0x08048749 <+53>: mov %eax,(%esp)
    0x0804874c <+56>: call 0x80485b8 <_ZNSolsEi@plt>
    0x08048751 <+61>: movl $0x8048638,0x4(%esp)
    0x08048759 <+69>: mov %eax,(%esp)
    0x0804875c <+72>: call 0x8048628 <_ZNSolsEPFRSoS_E@plt>
    0x08048761 <+77>: add $0x24,%esp
    ---Type <return> to continue, or q <return> to quit---
    0x08048764 <+80>: pop %ebx
    0x08048765 <+81>: pop %ebp
    0x08048766 <+82>: ret


    PHP Code:
    #include<iostream>
    using namespace std;
    int *p;
    void check()
    {
    auto int a=34;
    p=&a;

    }
    int main()

    {
    check();

    cout<<"value is:"<<*p<<endl;
    cout<<"valueq is:"<<*p<<endl;
    return 
    0;


    Output:

    value is:34
    valueq is:-1217201928


    Disassemble:

    Breakpoint 1 at 0x804872e
    (gdb) r
    Starting program: /root/test

    Breakpoint 1, 0x0804872e in main ()
    (gdb) disassemble
    Dump of assembler code for function main:
    0x0804872b <+0>: push %ebp
    0x0804872c <+1>: mov %esp,%ebp
    => 0x0804872e <+3>: and $0xfffffff0,%esp
    0x08048731 <+6>: push %ebx
    0x08048732 <+7>: sub $0x1c,%esp
    0x08048735 <+10>: call 0x8048714 <_Z5checkv>
    0x0804873a <+15>: mov 0x804a0d4,%eax
    0x0804873f <+20>: mov (%eax),%ebx
    0x08048741 <+22>: movl $0x80488e0,0x4(%esp)
    0x08048749 <+30>: movl $0x804a040,(%esp)
    0x08048750 <+37>: call 0x8048618 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_E S5_PKc@plt>
    0x08048755 <+42>: mov %ebx,0x4(%esp)
    0x08048759 <+46>: mov %eax,(%esp)
    0x0804875c <+49>: call 0x80485b8 <_ZNSolsEi@plt>
    0x08048761 <+54>: movl $0x8048638,0x4(%esp)
    0x08048769 <+62>: mov %eax,(%esp)
    0x0804876c <+65>: call 0x8048628 <_ZNSolsEPFRSoS_E@plt>
    0x08048771 <+70>: mov 0x804a0d4,%eax
    0x08048776 <+75>: mov (%eax),%ebx
    ---Type <return> to continue, or q <return> to quit---
    0x08048778 <+77>: movl $0x80488ea,0x4(%esp)
    0x08048780 <+85>: movl $0x804a040,(%esp)
    0x08048787 <+92>: call 0x8048618 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_E S5_PKc@plt>
    0x0804878c <+97>: mov %ebx,0x4(%esp)
    0x08048790 <+101>: mov %eax,(%esp)
    0x08048793 <+104>: call 0x80485b8 <_ZNSolsEi@plt>
    0x08048798 <+109>: movl $0x8048638,0x4(%esp)
    0x080487a0 <+117>: mov %eax,(%esp)
    0x080487a3 <+120>: call 0x8048628 <_ZNSolsEPFRSoS_E@plt>
    0x080487a8 <+125>: mov $0x0,%eax
    0x080487ad <+130>: add $0x1c,%esp
    0x080487b0 <+133>: pop %ebx
    0x080487b1 <+134>: mov %ebp,%esp
    0x080487b3 <+136>: pop %ebp
    0x080487b4 <+137>: ret

    Breakpoint 2, 0x0804871a in check() ()
    (gdb) disassemble
    Dump of assembler code for function _Z5checkv:
    0x08048714 <+0>: push %ebp
    0x08048715 <+1>: mov %esp,%ebp
    0x08048717 <+3>: sub $0x10,%esp
    => 0x0804871a <+6>: movl $0x22,-0x4(%ebp)
    0x08048721 <+13>: lea -0x4(%ebp),%eax
    0x08048724 <+16>: mov %eax,0x804a0d4
    0x08048729 <+21>: leave
    0x0804872a <+22>: ret
    Hacking Is a Matter of Time Knowledge and Patience

  3. #3
    @fb1hs2

    See the code u gave poses a situation know as (undefined behavior ) as refered in ISO C (http://www.open-std.org/jtc1/sc22/wg...docs/n1124.pdf) ISO efforts to make C portable by providing a standard." derefrencing a Pointer to local stack variable after function has returned" results in undefined behaviors according to n1124. So we cant generally answer to this situation in x86 terms (Undefined behavior will produce different or un expected results on different platforms)

    But yet i will answer this question

    First of all auto is a " storage type specifier " k&r says auto is a placebo ( medicine with on effect) , even a local stack variable with no auto keyword specified will be destroyed after function returns ..

    in case of x86 all the local variables are located on stack ,so even after the function returns the stack memory would still be there , but might be overwritten if another function is called

    i will give u an example, this code is self explaining

    Code:
    #define WIN32_LEAN_AND_MEAN // skip some un nesessary includes
    
    #include <windows.h>
    #include<stdio.h>
    int *p;
    
    DWORD* ESP_TRACKER;
    
    DWORD* EIP_TRACKER;
    
    void check() 
    {
            // PUSH EBP 
    		int a = 88; // address ebp - 4 
            p=&a; 
    		
    }
    
    
    int main() // ebp +4 return address
    {
    
    
    		check();
            __asm { 
    		
    		mov ESP_TRACKER, esp
    		
    		
    		};
    		
    		// stack cleareance sub esp, no. of param new frame aligned 
    		
    		ESP_TRACKER = ESP_TRACKER - 3 ;// 3 DWORD's pass the ESP, 1: return address 2 : OLD EBP 3: stack local variables which is int a;
    		
    		
    		printf("value of your varible from ESP ooffset %d\n", *ESP_TRACKER); // stack local varible still valid offset from ESP
    		// Stack restored here __cdecl type  sub esp, num of arguments 
    		
    		/* call printf disassembly
    		
    		push DWORD PTR[p] //corrputs the old ret address 
    		push DWORD PTR[STRING] // corrupts the OLD saved EBP
    		call __imp__printf // corrputs the value that is int a;
    		*/
    		__asm
    		{
    			// EIP capture technique used by various shellcodes
    			call next
    			next:
    			pop eax // get EIP
    			sub eax, 8 // compensated 8 opcodes
    			mov EIP_TRACKER, eax
    			
    			}
    		printf("address of a and RET address are same %p == %p\n", *p, EIP_TRACKER); // stack changed due to stack cleareance and overwritted by parameters of printf
    		
            return 0;
    }
    OUTPUT


    value of your varible from ESP ooffset 88
    address of EBP is 0121104E 0121104E

  4. #4
    Security Researcher fb1h2s's Avatar
    Join Date
    Jul 2010
    Location
    India
    Posts
    616
    Blog Entries
    32
    @rashid thanks for you'r valuable points.

    Currently we are dealing with Linux systems, and I believe you have tested it on windows but the result would be same for all x86 systems, you have already mentioned that .

    Any way yes its coz of the stack not getting cleared automatically unless a Function call is made or is asked to overwrite . Since Auto variable has only got scope inside {} brackets , after the call the value on stack is ready to be overwritten. So for first "COUT" the value would be there in stack un altered, but the second "COUT" the value would not be there due to the previous printf call.

    You missed to discuss on this :


    PHP Code:
    #include<iostream>
    using namespace std;
    int *p;
    void check()
    {
    auto int a=34;
    p=&a;
    cout<<"value is:"<<*p<<endl;

    }
    int main()

    {
    check();

    cout<<"value is:"<<*p<<endl;
    cout<<"valueq is:"<<*p<<endl;
    return 
    0;


    Output:
    value is:34
    value is:34
    valueq is:34
    Hacking Is a Matter of Time Knowledge and Patience

  5. #5
    @fb1hs2

    well check again i said

    "Undefined behavior will produce different or un expected results on different platforms" by platforms i meant different implementations

    your code gives me following output on x86 win7 MSVC 10
    value is:34 // stack frame check() valid called from inside
    value is:34 // value *p pushed onto the stack before cout is called
    value is:3536864 // old stack frame corrupted due to previous call *p points to overwritten value

    And Again you have to understand that its an "Undefined behavior" according to ISO C when , ISO itself say that it may produced unexpected behavior on different platforms we cant dispute about it .

  6. #6
    Garage Member
    Join Date
    Aug 2012
    Location
    India
    Posts
    97
    Blog Entries
    1
    I must say it's seriously depicting undefined behavior on different platforms.
    I tested this on ideone.com and the output was ->

    value is :88
    value is :88
    value is :88


    while on Visual 2010, it was ->

    value is :88
    value is :1445981504
    value is :1445981504


    Note : I'm using 3 COUT statements..
    Anyone who stops learning is old, whether at twenty or eighty. Anyone who
    keeps learning stays young. The greatest thing in life is to keep your mind young.
    - Henry Ford

  7. #7
    after the first cout , the stack is altered and we are getting a garbage value in the second cout ..
    I have written a new code , and in this code i have used two functions and got the following output ->

    #######
    code
    #######

    Code:
    #include<iostream>
    using namespace std;
    
    int *p;
    
    void check()
    {
            auto int a=88;
            p=&a;
    }
    
    void stack()
    {
            int b;
            b=100;
    }
    
    
    
    int main()
    {
    
            check();
            
    
            cout<<"value is :"<<*p<<endl;
            cout<<"address is "<<p<<endl;
            cout<<"value is :"<<*p<<endl;
            cout<<"address is "<<p<<endl;
            
            stack();
            
            cout<<"value is :"<<*p<<endl;
            cout<<"address is "<<p<<endl;
            cout<<"value is :"<<*p<<endl;
            cout<<"address is "<<p<<endl;
            
            return 0;
    }

    #######################
    output of the code
    #######################


    Code:
    value is :88
    address is 0x7fff9c9b89ac
    value is :32591
    address is 0x7fff9c9b89ac
    value is :100
    address is 0x7fff9c9b89ac
    value is :32591
    address is 0x7fff9c9b89ac


    The second function is getting the same stack which the first function was having .. and even both of them are giving the same garbage value ..
    why ???

  8. #8
    Garage Member
    Join Date
    Aug 2012
    Location
    India
    Posts
    97
    Blog Entries
    1
    I was searching the above question, and this maybe something relevant -> why-is-a-function-executed-from-the-same-memory-address-each-time

    Cheers.
    Anyone who stops learning is old, whether at twenty or eighty. Anyone who
    keeps learning stays young. The greatest thing in life is to keep your mind young.
    - Henry Ford

  9. #9
    guess all of you know this already , Memory is Never Actually Allocated or Deallocated...We only change esp for this ...its is not like we are having something like malloc()

    When i say Global ptr p=&local_var ,i have address of particular Memory Location ,so does not matter function ends ...it will show the same value untill or unless some another functions called and overwrite the memory location we are pointing to ...(it will overwrite as logically our previous function ends )

    In your case when u use "cout" it needs a call ,so same stack is assigned for that call .and get overwritten .

    finally if u want to do some more checks try to do operations that did not need call (into lib functions) and check value in debugger ...it will be same untill u overwrite the Memory Location ..

  10. #10
    Security Researcher fb1h2s's Avatar
    Join Date
    Jul 2010
    Location
    India
    Posts
    616
    Blog Entries
    32
    Adding valuable points from Dhanesh over facebook here.

    Dhanesh Kizhakkinan whats the issue here?
    If you are accessing a local variable outside its scope, the value returned can be anything - (basic stack framing for local variables inside a function).
    Monday at 05:41 Like

    Rahul Sasi Dhanesh Kizhakkinan Yea check my comments and the second code I have put up
    Monday at 05:43 Like

    Dhanesh Kizhakkinan The 4th post's code snippet?
    Again same case - whatever the code is doing is undefined behavior.
    Depending upon compiler/processor architecture and compiler optimization, the outpu...See More
    Monday at 05:53 Like 1

    Rahul Sasi Well Undefined :| it should be, but we are getting the same value if the second "count" was to clear the stack how come a third one made it not clear them. And yes this depends on compiler|processor , I dint check it on windows, would love to see the OP if some one tries .
    Monday at 06:00 Like

    Dhanesh Kizhakkinan It depends on the optimization:
    with optimization it will be 34 for everything
    without optimization: the last one will be changed.
    Tested on VS2010, Win7, x86
    Hacking Is a Matter of Time Knowledge and Patience

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •