CS120 - Day 6 - Strings & Dynamic Memory Allocation ----------------------------------------------------- String Functions ----------------------------------------------- - use pointer notation - memory must be allocated before use!!!!! - often use const to prevent changes to arguments - stdlib.h string conversion functions - double atof(const char *s) - int atoi(const char *s) - double strtod(const char *s, char **endp) - stdio.h string i/o functions - puts(s) - gets(s) - very insecure - may overwrite memory not allocated to your program! - fgets(s, MAXSIZE, stdin) - must allocate memory for s first! - string.h string manipulation functions, - strlen - char *strcpy(char *to, const char *from) - copy from -> to - return to - strncpy(to, from, howmany) - char *strcat(char *to, const char *from) - concatenate from to to (to = to + from) - return to - int strcmp(const char *s1, const char *s2) - compare s1 to s2 - return 0 if same, <0 if s1 < s2, >0 if s1 > s2 - command line arguments main(int argc, char *argv[]) argc is count of arguments, including program name argv[0] is program name argv[i] is ith argument (string) >>>> game.c example with strings and command-line arguments <<<< >>>> exercise1.c exercise1.h <<<< Dynamic memory allocation ----------- -dynamic memory is allocated on the heap -persists until it is freed -can return char* from functions, unlike char[] - size_t is data type for sizes of things (use with sizeof) - void *calloc (size_t numels, size_t sizeofel) - makes array of numels each of size sizeofel, init to 0 - returns pointer to memory - use typecast - void *malloc (size_t size) - creates memory block of given total size - returns pointer to start of memory - use typecast to specific base data type - void *realloc (void *ptr, size_t size) - moves memory at ptr to new place with new size - ptr should be previous *alloc return value - size is as in malloc, or (numels*sizeel) - if new size is bigger, new space uninitialized - use typecast - if any memory function fails it returns null char * memory = malloc(4); if (!memory) //remember null == 0, 0 := false failed to allocate memory ! deallocating memory - void free(void *ptr) - deallocates the memory at address ptr - ptr must be previous *alloc return value - ptr is no longer valid >>>> exercise2.c exercise2.h <<<< A few (more) usage examples: - use within function float * dynarray (int size) { float *farray; farray = (float *) calloc(size, sizeof(float)); return farray; }; main() { float * fdynarray; int size; printf("enter float array size"); scanf("%d", &size); fdynarray = dynarray(size); fdynarray[3] = 23.4; *(fdynarray+3) = 23.4; } - use to double array for example int size = 10, *array; array = (int *) calloc(size, sizeof(int)); /* or array = (int *) malloc(size*sizeof(int)); */ temp = (int *) realloc(array, size*2*sizeof(int)); if (temp) /* not NULL so good to go */ array = temp; else printf("not enough memory\n"); Valgrind ============================================== - to use: run program normally as you would from the command-line, but with "valgrind" prepended: >valgrind ./aout arg1 arg2 etc - check for memory leaks -malloc'd but not free'd - also finds invalid memory writes (writing past end of array) - "still reachable" means you forgot to call free but you still can int main() { char * mem = malloc(4); return 0; } //Should call free before return, doesn't really matter - "definitely lost" means you cannot call free because the pointer is gone void func() { char * mem = malloc(4); } - the pointer mem is gone once the function returns - imagine if the Chrome browser called func() 1000 times a second - Chrome would eat up more and more memory, slowing down your computer - eventually it would crash - your programs must not have memory leaks after the first memory assignment - NOTE: the various profiling tools (valgrind, gprof, etc.) are not compatible with each other. You can't compile for multiple ones at a time. Use makefiles to create a different rule for each.