static vs automatic storage classes three types of memory
play

static vs automatic storage classes Three types of memory - PowerPoint PPT Presentation

static vs automatic storage classes Three types of memory allocations static storage class means variable persists through static allocation: for globals and any static the life of the program variables in functions automatic storage


  1. static vs automatic storage classes Three types of memory allocations � static storage class means variable persists through � static allocation: for globals and any static the life of the program variables in functions � automatic storage class means variable exists only � Allocation on the stack: automatic variables during its scope are said to be “allocated on the stack” � When you declare a variable outside any functions, � Allocation on the heap: dynamic memory it has static storage class (global) allocation takes memory off the heap (malloc, � When you declare a variable inside a function, it has new) automatic storage class, unless you put the static keyword in front of it: static int a=0; //the value will persist until program exits Static allocation What is the “stack”? � Consider the following simple program: int funcB(void) � Initialized static variables are part of the { int i2,j2; float f2; binary executable. When the program gets i2=j2=2; f2=2.0f; printf("in B\n"); //set break point here loaded into memory, so do these variables return 0; } � Un-initialized static variables are not part of int funcA(void) the binary exe. They are automatically { int i,j; float f; allocated when the program gets loaded and i=j=1; f=1.0f; printf("in A\n"); initialized to 0 (but always initialize your var. funcB(); return 0; anyway). } int main(int argc, char* argv[]) � Either way, they exist from the start of the { funcA(); program to the finish. return 0; } 1

  2. Display the call stack shows: Using the debugger we can show that: + &j2 0x0012fec4 + &i2 0x0012fec8 + &j 0x0012ff24 funcB() line 12 + &i 0x0012ff28 funcA() line 24 Look at the memory: 0012FEC4 02 00 00 00 02 00 00 00 2C FF 12 00 ........,ÿ.. main(int 1, char * * 0x00430e90) line 30 0012FED0 CE 10 40 00 80 FF 12 00 00 00 00 00 Î.@..ÿ...... mainCRTStartup() line 206 + 25 bytes 0012FEDC 00 F0 FD 7F CC CC CC CC CC CC CC CC .ðý.ÌÌÌÌÌÌÌÌ KERNEL32! 77e814c7() 0012FEE8 CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌ 0012FEF4 CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌ 0012FF00 CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌ � When a function is called it is “pushed” onto the top 0012FF0C CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌ 0012FF18 CC CC CC CC CC CC CC CC 00 00 80 3F ÌÌÌÌÌÌÌÌ...? of the stack and when it returns, it is “popped” off the 0012FF24 01 00 00 00 01 00 00 00 80 FF 12 00 .........ÿ.. 0012FF30 1D 11 40 00 00 00 00 00 00 00 00 00 ..@......... top 0012FF3C 00 F0 FD 7F CC CC CC CC CC CC CC CC .ðý.ÌÌÌÌÌÌÌÌ 0012FF48 CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌ 0012FF54 CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌ 0012FF60 CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌ 0012FF6C CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌ 0012FF78 CC CC CC CC CC CC CC CC C0 FF 12 00 ÌÌÌÌÌÌÌÌÀÿ.. Stack cont’d Is this good code? Why? � Notice the stack starts from a high memory address char *f() { 1. and grows downwards. char result[80]; sprintf(result,"anything will do"); � Automatic variables (allocated on the stack) are part return(result); of an activation record } � Activation record is a chunk of memory allocated on int g() 2. { the top of the stack that holds: char *p; � Automatic variables p = f(); � Parameters printf("f() returns: %s\n",p); � Return address } � Cpu register values to be restored on return � Every function call creates new activation record (pushed on top of stack) � On return, the activation record is popped. 2

  3. Stack corruption Memory allocation off the heap � Allocate with malloc(), new //A few examples: � Must be freed with corresponding free(), char buf[30],str[30]; delete str[0]=‘a’; str[1]=‘b’; str[2]=‘c’; � Once allocated, memory persists until strcpy(buf,str); termination char a; int b=10; � Do not double free, or double delete memcpy(&a,&b,sizeof(b)); � The proper way to return a buffer from a � Is particularly nasty because: function is to � Doesn’t always generate seg fault right away (the stack is your memory) � Pass in a chunk of pre-allocated memory � Corrupting the activation record can alter the register values, return � Or allocate memory off the heap with malloc(), address etc of the previous function new and return that � Behavior is completely undefined (but may actually work) Signals Signals � Are interrupts � Unexpected/unpredictable asynchronous events � floating point error � death of a child � interval timer expired (alarm clock) � control-C (termination request) Haviland – Ch. 6 � control-Z (suspend request) � When the kernel recognizes an event, it sends a signal to the process. � Normal processes may send signals. 3

  4. What is an interrupt? What are signals for? � An interrupt is an event (generated by � To tell the program some unexpected event has software or hardware) that causes the happened processor to stop what it’s currently doing, � When a program forks into 2 or more processes, rarely do they execute independently. and transfer control to a handler for the � The processes usually require some form of interrupt synchronization, often handled by signals. � When the handler finishes, the processor � To transfer data between processes, we will use (usually) resumes what it was doing pipes and sockets (coming soon). � Signals are generated by � Example: when you type at the keyboard � machine interrupts � Completely transparent to the program � the program itself, other programs or the user. Software Interrupts Some common signals � SIGABRT – sent by abort(), causes termination, � <sys/signal.h> lists the signal types on CDF. core dump � SIGINT – caused by the “interrupt key” (ctrl-c) � “man 7 signal” (“man 5 signal” on Solaris) � SIGKILL – causes process termination, can’t alter gives some description of various signals default behavior � SIGTERM, SIGABRT, SIGKILL � SIGCHLD – child process terminated � SIGSEGV, SIGBUS � SIGFPE – floating point exception, causes abnormal � SIGSTOP, SIGCONT termination � SIGSEGV – illegal memory reference, causes � SIGCHLD termination, core dump � SIGPIPE � SIGSTP, SIGCONT – stop the process (ctrl-z) and resume execution, respectively 4

  5. Default actions Signal handlers � Each signal has a default action: � When a program receives a signal, control is immediately passed to a function called a � terminate signal handler. � stop � The signal handler function can execute � ignore some statements and exit in 3 different ways: � The default action can be changed for most signal types using the sigaction() � return control to the place in the program which was executing when the signal occurred. function. The exceptions are SIGKILL and � return control to some other point in the program. SIGSTOP (not the same at SIGSTP). � terminate the program by calling exit. Unix signal internals Signal handler array � For each process, Unix maintains a table of � Each process has the following information actions that should be performed for each kind re. Signals: of signal. � An array of entries called the signal handler array � Each entry of the signal handler array can have (describes what to do when each type of signal is one of 3 settings: received) � Signal can be ignored (value = 1) � An array of bits called the pending signal bitmap (1 bit per signal type – has signal for that type � Use default action for Signal (value = 0) been received?) � Use user installed handler (value = address � Signals may not be processed immediately of handler) � No count for number of signal received (1 bit) 5

  6. Signals and fork(), exec() sigaction() Install a signal handler, act , for the signal sig . � � On fork(): int sigaction(int sig, const struct sigaction *act, � Signal handler array is inherited across a fork() struct sigaction *oldact); � But the pending signal bitmap is cleared Struct defined in <signal.h> to fill in to pass in for act . � � On exec(): struct sigaction { � Pending signal bitmap is left as is /* SIG_DFL, SIG_IGN, or pointer to function */ void (*sa_handler)(int); � All user installed handlers cleared (set to 0) in signal sigset_t sa_mask; /*Signals to block during handler*/ handler array int sa_flags; /* flags and options */ }; You may come across various extensions, including another field in � the sigaction struct for a function to catch signals. More about sigaction structure Signal sets � The 1 st field sa_handler is a function pointer; can be 1 of 3 values: � Given by the type sigset_t � SIG_DFL – symbolic name, restore default � Used to describe a set of signals (SIGINT, handler SIGCHLD…etc) � SIG_IGN – ignore this signal � Initialize set with: � Or the address of your signal handler function � sigemptyset(sigset_t * set) � 2 nd field sa_mask gives a set of signals to be � sigfillset(sigset_t * set) blocked during the execution of the handler. � Manipulate with: The blocked signals aren’t ignored, but put on � sigaddset(sigset_t * set, int signo) hold until handler finishes � sigdelset(sigset_t * set,int signo) � 3 rd field sa_flag is advanced, set it to 0 6

Recommend


More recommend