1 / 23

C – Scope, Lifetime, and the Stack

Learn about const pointers, pointer casting, activation records, stack layout, recursive functions, and the scope and lifetime of variables in C.

truluck
Download Presentation

C – Scope, Lifetime, and the Stack

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C – Scope, Lifetime,and the Stack CS/COE 0449 Jarrett Billingsley

  2. Class announcements • lab 3 is out? • project 1 is out? CS449

  3. More pointer stuff CS449

  4. const pointers • for any type T, a constT*is a read-only pointer to a T • you can read the data that it points to, but you can't write it • you can however change where the pointer points to const char* s = "hello"; s = "goodbye"; // fine! s[3] = 'x'; // COMPILER error! • const pointers are used when you want a pointer, but you want to promise that you won't change the thing that it points to. • e.g. strlen() takes a const char* - it reads from the string but will not modify it. • see 6_const_ptrs.c CS449 (2184)

  5. Pointer casting • casts convert from one type to another, like so: (type)value inta = 20, b = 25; double x = a / (double)b; // now it's 0.8 • you can cast pointers too float f = 3.567; int* p = (int*)&f; // p points to f... printf("%08x\n", *p); // interprets f as an int! • the computer does not care what bits represent • this kind of cast does not change anything in memory • f is still there and it still holds 3.567 • it only changes how we view that memory • see 6_ptr_casts.c (and the visualization linked below it) CS449 (2184)

  6. The Stack!!! CS449

  7. The flow of control • when the caller calls a function, where do we go? • when the callee's code is finished, where do we go? void knife() { spork++; spatula--; } void fork() { knife(); spoon++; } callee caller CS449

  8. What's the stack? • it's an area of memory provided to your program by the OS • when your program starts, it's already there • the stack holds information about function calls. • it's not a strict stack • you can read and write any part of it • but it grows and shrinks like a stack • and we use "push" and "pop" to describe that • each program* gets one stack • cause only one function is running at a time Memory Stack CS449

  9. Activation records (ARs) • when a function is called, a bunch of data is pushed onto the stack • this is the call's activation record(or "stack frame") • it contains local variables (including arguments) and the return address Stack int main() { int x, y; charbuf[5]; return0; } main's AR CS449

  10. The low-level layout • each variable (including array variables) gets enough bytes in the AR to hold its value • where the variable is located is up to the compiler when I compiled this on thoth, this is the arrangement I got: sizeof(int) == 4, so x gets 4 bytes sizeof(arr) == 3, so it gets 3 bytes sizezof(short) == 2, so.. yeah but what's all that grey space? idk lol, compiler does what it wants YOU DON'T NEED TO KNOW THE LOW-LEVEL LAYOUT! int x; char arr[3]; short y; CS449

  11. Call = push, return = pop (animated) • the stack grows when we call a function and shrinks when it exits main int main() { int x; fork(&x); return0; } void fork(int* ptr) { *ptr = knife(); } int knife() { return 10; } fork knife CS449

  12. Recursive functions (animated) • recursive functions work by using the call stack as an implicit stack data structure fact(5) int fact(int x) { if(x <= 2) { return x; } else { return x*fact(x–1); } } fact(4) fact(3) fact(2) CS449

  13. But they don't really go away. (animated) • the stack is used constantly • so it needs to be really fast • so we implement it as a pointer • the stack pointer (sp) sp push AR:sp -= (size of AR) pop AR: sp += (size of AR) but the AR's memory is still there. so if we call another function… this is where that garbage in uninitialized variables comes from! CS449

  14. Don't return stack arrays. • I think I showed this before "function returns address of local variable" • when func() returns, what happened to its variables? • you have no idea • you now have an invalid pointer • it points to who-knows-what • it might crash • it might expose secrets • who knows!! int main() { char* str = func(); printf("%s\n", str); return0; } char* func() { char str[10] = "hi there"; char* dummy = str; return dummy; } CS449

  15. Scope and Lifetime CS449

  16. Scope • scope is "where a name can be seen" • C has three levels of scope globals can be seen by any function in any file static globals can be seen by any function in one file locals can be seen by one function int main() { int x; } one.c two.c CS449

  17. Global variables are terrible • and you should almost never use them. • almost any problem where you think you need one can be instead solved by using a local and passing by reference. • there are legitimate uses for them, but… • unless you are being forced to use them… • avoid them. CS449

  18. Homestead (animated) • every variable takes up space in memory • memory is limited, and the "land" must be "bought and sold." memory must be allocated: reserved for a variable int x int* p float f and when no longer needed, deallocated: released for other use the language handles this process for you, for local and global variables. CS449

  19. Lifetime • lifetime is a little more subtle than scope... • it's the time betweenallocation and deallocation. • it's how long a value is "available" or "valid." • global variables last from program start to program exit • local variables' lifetime starts at their declaration, and ends at the closing brace that encloses them • though the compiler kinda optimizes this and just does one allocation at function start and one at function return CS449

  20. You're watching the Lifetime Channel voidfunc() { int f = 10; } int glob = 0x910B; int main() { int m = 10; func(); return0; } lifetime of glob lifetime of m lifetime of f time CS449

  21. Ownership • ownership answers the question: who is responsible for deallocating a piece of memory? • or: how do we know when it's okay to deallocate memory? • different languages deal with this in different ways. • Java uses garbage collection to do a lot of this. • C mostly sticks its fingers in its ears, goes "LA LA LA," and pretends the problem doesn't exist. • locals and globals are easy: • locals are owned by functions • so their memory is deallocated by the function that made them. • globals are owned by the program • so their memory is deallocated when the program ends. • but… CS449

  22. If only it were that simple public static voidmain(String[] args) { String s = func(); s = null; } String func() { String t = new String("hello"); return t; } • in this Java code: • what is the scope of each variable? • what is the object's lifetime? • the allocation happens at new. • but… where is it deallocated? • when? • by who? • important: the variables s and t and the object they point to have separate lifetimes. CS449

  23. Looking at this problem a different way • what is happening here is a conflict between ownership and lifetime. • the programmer wants the variable to live longer than the ownership will allow it. • but in C, there's no way to "transfer" the ownership. • Java sidesteps this problem: objects can have one or more owners, but if no one owns it, it is deallocated. • that's GC, and next class! int main() { char* str = func(); printf("%s\n", str); return0; } char* func() { char str[10] = "hi there"; char* dummy = str; return dummy; } CS449

More Related