
Reading Java Hello World... ‣ Textbook import java.io.*; public class HelloWorld { • New to C, Understanding Pointers, The malloc and free Functions, Why Dynamic Memory Allocation public static void main (String[] args) { System.out.println("Hello world"); • 2ed: "New to C" sidebar of 3.4, 3.10, 9.9.1-9.9.2 } • 1ed: "New to C" sidebar of 3.4, 3.11,10.9.1-10.9.2 CPSC 213 } C vs. Java C Hello World... Introduction to Computer Systems #include <stdio.h> main() { printf("Hello world\n"); Unit 1f } C, Pointers, and Dynamic Allocation 1 2 3 4 Java Syntax... vs. C Syntax New in C: Pointers C and Java Arrays and Pointers ‣ source files ‣ source files ‣ pointers: addresses in memory 0x00000000 ‣ In both languages 0x00000001 • .java is source file • .c is source file • locations are first-class citizens in C • an array is a list of items of the same type 0x00000002 • .h is header file • can go back and forth between location and value! • array elements are named by non-negative integers start with 0 0x00000003 ‣ including packages in source ‣ including headers in source ‣ pointer declaration: <type>* 0x00000004 • syntax for accessing element i of array b is b[i] • import java.io.* • #include <stdio.h> • int* b; // b is a POINTER to an INT 0x00000005 ‣ In Java ‣ printing ‣ printing 0x00000006 • printf("blah blah\n"); ‣ getting address of object: & • variable a stores a pointer to the array • System.out.println("blah blah"); . Pointers in C • int a; // a is an INT • b[x] = 0 means m[m[b] + x * sizeof(array-element)] ← 0 ‣ compile and run ‣ compile and run . • int* b = &a; // b is a pointer to a . • javac foo.java • gcc -g -o foo foo.c ‣ In C • ./foo 0x3e47ad40 • java foo ‣ de-referencing pointer: * • variable a can store a pointer to the array or the array itself • at Unix command line shell prompt • at command line (Linux, Windows, Mac) • a = 10; // assign the value 10 to a 0x3e47ad41 (Linux, Mac Terminal, Sparc, • b[x] = 0 means m[b + x * sizeof(array-element)] ← 0 0x3e47ad42 Cygwin on Windows) • *b = 10; // assign the value 10 to a or m[m[b] + x * sizeof(array-element)] ← 0 ‣ debug . ‣ edit, compile, run, debug (IDE) ‣ type casting is not typesafe . • dynamic arrays are just like all other pointers • gdb foo • Eclipse • char a[4]; // a 4 byte array . - stored in TYPE* • *((int*) a) = 1; // treat those four bytes as an INT 0xffffffff - access with either a[x] or *(a+x) 5 6 7 8 Example Example Pointer Arithmetic in C Question (from S3-C-pointer-math.c) ‣ The following two C programs are identical ‣ The following two C programs are identical ‣ Its purpose int *c; • an alternative way to access dynamic arrays to the a[i] int *a; int *a; int *a; int *a; void foo () { a[4] = 5; *(a+4) = 5; a[4] = 5; *(a+4) = 5; ‣ Adding or subtracting an integer index to a pointer // ... c = (int *) malloc (10*sizeof(int)); • results in a new pointer of the same type // ... ‣ For array access, the compiler would generate this code ‣ For array access, the compiler would generate this code • value of the pointer is offset by index times size of pointer’s referent c = &c[3]; *c = *&c[3]; • for example // ... r[0] ← a ld $a, r0 r[0] ← a ld $a, r0 - adding 3 to an int* yields a pointer value 12 larger than the original } r[1] ← 4 ld $4, r1 r[1] ← 4 ld $4, r1 r[2] ← 5 ld $5, r2 r[2] ← 5 ld $5, r2 ‣ Subtracting two pointers of the same type m[r[0]+4*r[1]] ← r[2] st r2, (r0,r1,4) m[r[0]+4*r[1]] ← r[2] st r2, (r0,r1,4) • results in an integer ‣ What is the equivalent Java statement to • gives number of referent-type elements between the two pointers • multiplying the index 4 by 4 (size of integer) to compute the array offset • multiplying the index 4 by 4 (size of integer) to compute the array offset • [A] c[0] = c[3]; • for example • [B] c[3] = c[6]; ‣ So, what does this tell you about pointer arithmetic in C? ‣ So, what does this tell you about pointer arithmetic in C? - (& a[7]) - (& a[2])) == 5 == (a+7) - (a+2) • [C] there is no typesafe equivalent ‣ other operators • [D] not valid, because you can’t take the address of a static in Java Adding X to a pointer of type Y*, adds X * sizeof(Y) • & X the address of X to the pointer’s memory-address value. • * X the value X points to 9 9 10 11 Looking more closely Looking more closely ‣ And in assembly language Example: Endianness of a Computer r[0] ← 0x2000 # r[0] = &c c = &c[3]; r[0] ← 0x2000 # r[0] = &c c = &c[3]; r[0] ← 0x2000 # r[0] = &c r[1] ← m[r[0]] # r[1] = c *c = *&c[3]; r[1] ← m[r[0]] # r[1] = c *c = *&c[3]; r[1] ← m[r[0]] # r[1] = c r[2] ← 12 # r[2] = 3 * sizeof(int) r[2] ← 12 # r[2] = 3 * sizeof(int) r[2] ← 12 # r[2] = 3 * sizeof(int) r[2] ← r[2]+r[1] # r[2] = c + 3 #include <stdio.h> r[2] ← r[2]+r[1] # r[2] = c + 3 r[2] ← r[2]+r[1] # r[2] = c + 3 m[r[0]] ← r[2] # c = c + 3 m[r[0]] ← r[2] # c = c + 3 m[r[0]] ← r[2] # c = c + 3 int main () { r[3] ← 3 # r[3] = 3 char a[4]; r[3] ← 3 # r[3] = 3 r[3] ← 3 # r[3] = 3 r[4] ← m[r[2]+4*r[3]] # r[4] = c[3] r[4] ← m[r[2]+4*r[3]] # r[4] = c[3] r[4] ← m[r[2]+4*r[3]] # r[4] = c[3] m[r[2]] ← r[4] # c[0] = c[3] *((int*)a) = 1; m[r[2]] ← r[4] # c[0] = c[3] m[r[2]] ← r[4] # c[0] = c[3] printf("a[0]=%d a[1]=%d a[2]=%d a[3]=%d\n",a[0],a[1],a[2],a[3]); } Before Before After ld $0x2000, r0 # r0 = &c ld (r0), r1 # r1 = c ld $12, r2 # r2 = 3*sizeof(int) 0x2000: 0x3000 0x2000: 0x3000 0x2000: 0x300c 0x3000: 0 0x3000: 0 0x3000: 0 add r1, r2 # r2 = c+3 0x3004: 1 0x3004: 1 0x3004: 1 st r2, (r0) # c = c+3 0x3008: 2 0x3008: 2 0x3008: 2 0x300c: 3 0x300c: 3 0x300c: 6 ld $3, r3 # r3 = 3 0x3010: 4 0x3010: 4 0x3010: 4 c[0] = c[3] ld (r2,r3,4), r4 # r4 = c[3] 0x3014: 5 0x3014: 5 0x3014: 5 st r4, (r2) # c[0] = c[3] 0x3018: 6 0x3018: 6 0x3018: 6 0x301c: 7 0x301c: 7 0x301c: 7 0x3020: 8 0x3020: 8 0x3020: 8 12 12 13 14 Dynamic Allocation in C and Java Considering Explicit Delete ‣ Let's extend the example to see • what might happen in bar() ‣ Programs can allocate memory dynamically ‣ Let's look at this example • and why a subsequent call to bat() would expose a serious bug • allocation reserves a range of memory for a purpose struct MBuf * receive () { struct MBuf * receive () { struct MBuf* mBuf = (struct MBuf*) malloc (sizeof (struct MBuf)); struct MBuf* mBuf = (struct MBuf*) malloc (sizeof (struct MBuf)); • in Java, instances of classes are allocated by the new statement ... ... return mBuf; • in C, byte ranges are allocated by call to malloc function return mBuf; } } ‣ Wise management of memory requires deallocation void foo () { void foo () { • memory is a scare resource struct MBuf* mb = receive (); struct MBuf* mb = receive (); Dynamic Allocation bar (mb); bar (mb); • deallocation frees previously allocated memory for later re-use free (mb); free (mb); } } • Java and C take different approaches to deallocation void MBuf* aMB; ‣ How is memory deallocated in Java? • is it safe to free mb where it is freed? • what bad thing can happen? void bar (MBuf* mb) { aMB = mb; } ‣ Deallocation in C void bat () { This statement writes to • programs must explicitly deallocate memory by calling the free function aMB->x = 0; unallocated (or re-allocated) memory. } • free frees the memory immediately, with no check to see if its still in use 15 16 17 18 Dangling Pointers Avoiding Dangling Pointers in C Avoiding dynamic allocation Reference Counting ‣ A dangling pointer is ‣ Understand the problem ‣ If procedure returns value of dynamically allocated object ‣ Use reference counting to track object use • a pointer to an object that has been freed • when allocation and free appear in different places in your code • allocate that object in caller and pass pointer to it to callee • any procedure that stores a reference increments the count • could point to unallocated memory or to another object • for example, when a procedure returns a pointer to something it allocates • good if caller can allocate on stack or can do both malloc / free itself • any procedure that discards a reference decrements the count ‣ Why they are a problem ‣ Avoid the problem cases, if possible • the object is freed when count goes to zero struct MBuf * receive () { • program thinks its writing to object of type X, but isn’t • restrict dynamic allocation/free to single procedure, if possible struct MBuf* mBuf = (struct MBuf*) malloc (sizeof (struct MBuf)); struct MBuf* malloc_Mbuf () { ... • it may be writing to an object of type Y, consider this sequence of events struct MBuf* mb = (struct MBuf* mb) malloc (sizeof (struct MBuf)); • don’t write procedures that return pointers, if possible return mBuf; mb->ref_count = 1; } • use local variables instead, where possible return mb; (1) Before free: (2) After free: void foo () { } - since local variables are automatically allocated on call and freed on return through stack aMB: 0x2000 aMB: 0x2000 struct MBuf* mb = receive (); dangling ‣ Engineer for memory management, if necessary bar (mb); void keep_reference (struct MBuf* mb) { pointer free (mb); void receive (struct MBuf* mBuf) { mb->ref_count ++; 0x2000: a struct mbuf 0x2000: free memory } ..
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages2 Page
-
File Size-