Page 1 of 1

The attached files, Memory.c, Memory.h, and MemLeak.h provide a layer of code between an application and C dynamic memor

Posted: Sun May 15, 2022 7:53 am
by answerhappygod
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 1
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 1 (97.71 KiB) Viewed 55 times
--------------------------------------------------------------------
pascal.c
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 2
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 2 (66.39 KiB) Viewed 55 times
--------------------------------------------------------------------
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 3
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 3 (16.04 KiB) Viewed 55 times
--------------------------------------------------------------------
Memory.c
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 4
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 4 (68.25 KiB) Viewed 55 times
--------------------------------------------------------------------
Memory.h
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 5
The Attached Files Memory C Memory H And Memleak H Provide A Layer Of Code Between An Application And C Dynamic Memor 5 (50.53 KiB) Viewed 55 times
The attached files, Memory.c, Memory.h, and MemLeak.h provide a layer of code between an application and C dynamic memory API's that detects memory leaks and certain out-of-bounds modification of allocated memory. Copy last week's assignment code, pascal.c, to m_pascal.c, and add this code to the copy. Correct any dynamic memory problems that are uncovered by this code, and upload m_pascal.c to this assignment. Use the following compile command to create Memory.o from Memory.c and Memory.h: gcc -c Memory.c -I. -DMEMORY_TRAK Use the following compile command to create your m_pascal executable linked with the memory leak layer. gcc -o m_pascal m_pascal.c Memory.O -I. -lc When there are no memory problems, the memory code will display the following at the end of execution: Memory Track Report for m_pascal.c Memory Track Report complete Any memory errors will display between these two lines, such as: MA31 size 48 Memory Track Report for m_pascal.c allocated area 0x55d50c059200 trace 010000000000000037000000 a 5000000 *. Memory Track Report complete showing one allocation made at line 31 in the program which was not freed. Need Help?

1 8 9 12 int scp: 17 21 Chw_pascal) newPascal(lines) #include<stdio.h> 2 #include<stdlib.h> 3 4 #include <string.h> 5 #include <ctype.h> 6 7 #include "safe_string.h" #define LINES 12 static char erri[ ] = "memory alloction error %s requesting %d bytes\n"; 10 void allocErr(char *who, long siz) { 11 fprintf(stderr, erri, who, siz); exit(1); 13 } 14 int *arrayCopy(int *ar, int sz) { 15 16 int ix; long msz; 18 msz = (sz + 1) + sizeof(int); 19 if ( == (cp = (int *)malloc(sz))) 20 allocErr(arrayCopy", msz); for (ix = 0; ix < sz; ++ix) 22 { 23 cp[ix] = ar[ix]; 24 } 25 cp[sz) = -1; 26 return cpi 27 ) 28 int **newPascal(int lines) { int array: 30 int **triangle; int ix, jx; long maz; msz = lines * sizeof(int); 34 // error in memory allocation 35 if (0 == (array = (int *)malloc(msz))) 36 allocErr(newPascall", msz); 37 msz = (lines + 1) + sizeof(int *); 38 if (0 == (triangle = (int **)malloc(msz))) 39 allocErr("newPascal2", msz); 40 //allocates memory and creates the array 41 for (ix = 0; ix < lines; ++ix) 42 { array[ix] = 1; for (jx = ix - 1; jx > 1; --jx) 45 { 46 array[jx] += array[jx - 1); 47 > triangle(ix) = arrayCopy(array, ix + 1); 49 } 29 31 32 33 43 44 48

49 50 51 55 56 59 60 62 63 64 65 66 Chw_pascal) | fmt Triangle(tri) } triangle[lines] = 0; //returns the created array 52 return triangle; 53 } 54 //function to free memory allocation void delPascal(int **tri) { int ix; 57 ix -º; 58 while (!= tri[ix]) { //frees memory allocated to each element 61 free(trifix]); ix + 1; } free(tri);//frees memory allocated to array } void rawTriangle(int **tri) { 67 int ix, jx; ix = ; while (o tri[ix]) { jx = 0; 72 while (tri[ix][jx) = -1) 73 < 74 printf("%d", tri[ix][jx]); 75 jx += 1; 76 > printf("\n"); 78 ix + 1; 79 } } 81 * Displays a formatted Pascal's Triangle from the two-dimensional array tri. int ** is the same type *as int ID, but with int , it is not necessary to explicitly define the size of the arrays. * In Pascal's Triangle, each element trill points to a int of variable size. The last element in 85 *the array is -1, a sentinel indicating end-of-array. The last element, tri[last] is indicated with a * null pointer. 68 69 70 71 77 80 82 83 84 86 87 88 89 90 91 92 93 94 95 void fmt Triangle(int **tri) { int ix, jx, sz, mx; char **arr; char buf[12]; /* to be used for sprintf(), a buffer large enough to contain formatted 11-digit integers / sz = ; //assign lines to rows int space = @, rows = LINES; //loop to iterate over all rows for (ix = 0; ix <= rows; ++ix, jx = 0) { for (space - ®; space <- rows - ix; ++space) { 96 97

Chw_pascal) Ffmt Triangle(tri) 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 for (space = €; space <= rows - ix; ++space) { //fills whitespace until rows-ix times printf(""); > while (jx !-- 1 && tri[ix][jx) != -1) { //checks if tri(element) is -1 or else prints the element preceded and succeeded by whitespaces printf("%d", tri[ix][jx]); ++jx; } //prints new line printf("\n"); } /* calculate the size in the input array tri - see rawTriangle() */ /* allocate arr, an array of char * to store the formatted strings */ /* because arr is a pointer to an array of char *, it is a char ***/ /* use a variable to keep track of the maximum length formatted line */ /* use an index variable in a while loop to index each line. */ /* while loop termination is = tri[ix) */ /* in the while loop / /* use sprintf() to format the first element of the current array */ /* assign the result to the array of saved formatted strings #/ /* in an inner while loop, format each succeeding triangle value with sprintf() */ /* append the formatted result to the saved formatted string */ /* the end of the inner loop is indicated by an array element of -1 */ /* when the inner loop finishes, update the maximum formatted string length */ /* incrementing the outer loop index goes to the next line in the triangle */ /* print the formatted strings - the key to printing the correct amount of indentation */ /* is to print an empty string with a varible length field with specification */ /* before printing the formatted string - the length with depend upon the difference between */ /* the maximum string length and the current string length */ /* after the strings are printed, free all the dynamically allocated storage */ } int main(int arge, char *argv[]) { int **triangle; triangle = newPascal(LINES); rawTriangle(triangle); fmt Triangle(triangle); delPascal(triangle); return; }

h MemLeak) No Selection #ifndef MEMLEAK_INCLUDE_GUARD 2 #define MEMLEAK_INCLUDE_GUARD 3 #include "Memory.h" #define STRINGIFY(x) #x #define TOSTRING(X) STRINGIFY(x) #define malloc(a) malloc(a, "MA" TOSTRING( __LINE__)) #define calloc(a,b) cAlloc(a, b, "CA" TOSTRING(__LINE__)) #define free(a) mFreela, "F" TOSTRING( __LINE__)) #define trak() trakReport(__FILE__) 10 #endit 11

C Memory) No Selection 1 Hinclude <stdlib.h> 2 #include <string.h> 3 #include <stdio.h> #include <errno.h> #include <ctype.h> #define MEMORY_EXPORT #include "Memory.h" 4 5 6 7 8 * @brief A set of functions that provide wrappers around the basic * memory allocation routines in order to capture out-of-memory errors and to provide for optional recovery or graceful shutdown. Debugging fuctions also provide for memory allocation tracking and a memory loss report. * Author: Dan Evans 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 * An error message to capture the trace identifier passed to *the allocation or free function. The message is static so *that no additional allocation is necessary to create an error message when an allocation error has already occurred. * The x's are overlayed with the first 16 characters of the trace identifier 26 27 28 30 31 32 四四四部引弧田站mwwm』 昭 24 #define msgoffset 14 25 static char nomemmsg[] = "out of memory:XXXXXXXXXXXXXXXX"; * An error message for freeing a 0-pointer. 29 static char zeromsg[] - "freeing a ptr: XXXXXXXXXXXXXXXX"; An error message for freeing unallocated memory. 33 static char unalmsg[] = "unalloc free :XXXXXXXXXXXXXXXX"; 34 static void memoryError(char smsg, void *prm); 35 36 * The Memory ErrorBlock tracks the current memory error function. 37 * Memory ErrorBlock's are chained in a stack that is managed by 38 the push Memory ErrorFunction and popMemory ErrorFunction routines. 39 40 typedef struct MemoryErrorBlock 41 { 42 struct MemoryErrorBlock *next; 43 MemoryErrorFunc errorFunc; 44 void *parm; 45 } MemoryErrorBlock; 46 #define _tagSize 16 47 static const int tagSize = _tagsize; The base of the Memory ErrorBlock stack, which is always present. 49

49 50 51 52 C Memory) No Selection * The base of the Memory ErrorBlock stack, which is always present. static MemoryErrorBlock baseMemoryErrorBlock = {0, memoryError, 0); * A chain of free Memory ErrorBlock's to reduce the impact of stack addition and deletion on allocation. static MemoryErrorBlock #mebFree = 0; * A reference to the top Memory ErrorBlock on the stack. static MemoryErrorBlock #mebStack = &baseMemoryErrorBlock; 53 54 55 56 57 58 59 60 61 62 63 64 *Push a memory error function onto the stack, making it the * current memory error function. The current memory error function will be called if an allocation request returns a 0-pointer. * @param fnc the new memory error function * @param userdata a reference to opaque user data 65 66 68 印www忍四叫阳阳阳四部部配 void 69 pushMemoryErrorFunction(MemoryErrorFunc fnc, void *userdata) 70 { 71 MemoryErrorBlock #blk; 72 if (mebFree - 73 { 74 blk = (MemoryErrorBlock *)malloc(sizeof(MemoryErrorBlock)); 75 if (blku ) 76 { 77 mebStack->errorFunc("pushMemoryErrorFunction", (void *)®); 78 return; 79 } 80 } 81 else 82 { 83 blk mebFree; 84 mebFree - blk->next; 85 3 86 blk->errorFunc = fnc; 87 blk->next = meb Stack; 88 blk->parm = userdata; 89 mebStack = blk; } 90 91 92 93 + Pop the top of the memory error function stack, discarding the *top function and making the next function the current memory *error function. The base of the stack is a static MemoryErrorBlock that points to the generic memory error function, and is never popped. 94 95 96 97 void

C Memory) mAlloc(sz, trace) 145 if ((sttr = (struct StorTrak *)malloc(size)) == >| 146 { 147 memcpy(&nomemmsg(msgoffset), trace, tagsize); 148 mebStack->errorFunc(nomemmsg, mebStack->parm); 149 return : 150 } 151 sttr->link - trak; 152 trak = sttr; 153 sttr->size = sz; 154 memset(&sttr->label[(sizeof sttr->label) - fsz), 'A', fsz); 155 strncpy(sttr->label, trace, sizeof sttr->label); 156 stor = (char *) (sttr + 1); 157 memcpy(stor + sz, trakFence, fsz); 158 return stor 159 } 160 161 * A wrapper around the system calloc routine to allocate an initialized 162 * array of elements, the wrapper checks for a 163 *O-pointer return and calls the current memory error function on 164 * allocation failure. 165 * @param count the number of array elements to allocate 166 * @param size the size of each array element 167 * @param trace the caller trace message 168 * @return a pointer to the allocated array, the memory allocated 169 is initialized to zero; if allocation fails and the current 170 memory error function returns, the 0-pointer is returned 171 to the caller 172 173 void * 174 Calloc(unsigned count, unsigned size, char *trace) 175 { 176 charestor; 177 unsigned bytes; 178 bytes = count * size; 179 if ((stor = (void *)mAlloc (bytes, trace)) != ) 180 memset(stor, o, bytes); 181 return stori 182 } 183 int 184 mIsAlloc(void *area) 185 { 186 struct Stor Trak #sttr, *S: 187 sttr = (struct StorTrak *)area - 1; 188 sq = trak; 189 while (sq) 190 { if (s == sttr) 192 return 1; 193 Sq = sq->link; 191

C Memory) misAllocarea) 193 sq = sq->link il 194 195 return ; 196 } 197 void 198 mFree (void *area, char *trace) 199 { 200 struct StorTrak *sttr, **597 201 if (area ! ) 202 { 203 sttr = (struct StorTrak *)area - 1; 204 Sq=&trak; 205 while (*sq !=) 206 { 207 if (*s9 == sttr) 208 { 209 *59 = sttr->link; 210 if (memcmp((char *)area + sttr->size, trakFence, sizeof trakFence) != B) 211 report(area, sttr->label, sttr->size); 212 free(sttr); 213 return; 214 } 215 sq = &(sq)->link; 216 } 217 /* for the moment, assume allocated outside memory tracking 218 free (area); */ 219 memcpy(&unalmsg[msgoffset), trace, tagSize); 220 mebstack->errorFunc(unalmsg, mebstack->parm); 221 } 222 else 223 { memcpy(&zeromsg[msgoffset], trace, tagSize); 225 mebStack->errorFunc(zeromsg, mebstack->parm); 226 } } 228 229 * A wrapper around the system realloc routine to expand (or contract) 230 * a previously allocated storage area. The contents of the previously 231 * allocated area are copied to the beginning of the new area as *size permits, and the previously allocated area is freed. * In order to accomodate first-time allocation, a 0-pointer for the 234 * previous *The wrapper checks for a 0-pointer return and calls the current *memory error function on allocation failure. 237 * @param area the area to be expanded (or contracted); if O, the 238 requests defaults to a simple allocation request * @param size the size of requested area 240 * @param trace the caller trace message 241 * Breturn a pointer to the allocated array; the memory allocated 224 227 232 233 235 236 239

245 259 C Memory) No Selection 241 @return a pointer to the allocated array; the memory allocated 242 is initialized to the contents of the previously allocated area 243 as size permits, the remaining area is uninitialized; if 244 allocation fails and the current memory error function returns, the O-pointer is returned to the caller 246 247 void * 248 reAlloc void sarea, unsigned size, char *trace) 249 250 char *stori 251 struct StorTrak #sttr, **59: 252 if (area w ) 253 return malloc(size, trace); 254 sttr = (struct StorTrak *)area - 1; 255 sq &trak; 256 while (*sq != ) 257 { 258 if (*sq == sttr) break; 260 sq = &(#59)->link; 261 > 262 if (*sq == 0) 263 { 264 memcpy(&unalmsg[msgoffset), trace, tagSize); 265 mebStack->errorFunc(unalmsg, mebStack->parm); return ; > *5 = sttr->link; 269 if ((stor = (void *)mAlloc(size, trace)) != ) 270 memcpy(stor, area, sttr->size); 271 if (memcmp((char *)area + sttr->size, trakFence, sizeof trakFence) != 0) report(area, sttr->label, sttr->size); free(sttr); /* memory already removed from chain, no need for mFree / 274 return stori 275 > 276 static void 277 report(void *area, char *label, unsigned size) 278 { 279 int max: char hex(33), chr[17); unsigned char *cp; 283 fprintf(stderr, "allocated area %p trace %*.*s size %d\n", area, tagSize, tagSize, label, size); 284 max = (size > 16) ? 16 : size; cp = (unsigned char *)area; for (ct = ; ct < max; ++ct, ++cp) 287 { sprintf(&hex[ct + ct), "%02x", *cp); chr[ct] = (isalnum(*cp)) ? (char =) cp : '.'; 266 267 268 272 273 int ct: 280 281 282 285 286 288 289

297 C Memory) report(area, label, size) 288 sprintf(&hex[ct + ct), "%02x", *cp); 289 chr[at] = (isalnum(*cp)) ? (char *)cp : '.'; 290 } 291 for (; ct < 16; ++ct) 292 { 293 sprintf(&hex[ct + ct)," "); 294 chr[ct] =' 295 } 296 chr[16] = 0; fprintf(stderr," *s **\n", hex, chr); 298 if (memcmp((char *)area + size, trakFence, sizeof trakFence) != 8) 299 { 300 cp = (unsigned char *)area + size; 301 for (ct = ; ct < sizeof trakFence; ++ct, ++ cp) 302 < 303 sprintf(&hex[ct + ct), "%02x", *cp); 304 } 305 fprintf(stderr, fence corruption %s\n", hex); 306 } 307 } 308 void 309 trakReport(char *id) 310 { 311 struct StorTrak #sttr, **59: 312 int ct; 313 ct = ; 314 sq = &trak; 315 fprintf(stderr, "Memory Track Report for %s\n", id); 316 while (*sq != 0) 317 { 318 sttr - ; 319 ++ct; 320 report((void *) (sttr + 1), sttr->label, sttr->size); 321 Sq=&sttr->link; 322 } 323 fprintf(stderr, "Memory Track Report complete\n"); 324 } 325 #else 326 327 * A wrapper around the basic system memory allocation interface that 328 adds memory tracking and out-of-bounds write analysis. 329 330 void * 331 malloc(unsigned sz, char *trace) 332 { 333 char *stori 334 if ((stor = (char *)malloc(sz)) == B) 335 { 336 memcpy(&nomemmsg[msgoffset), trace, tagSize);

C Memory ) mAlloc(sz, trace) 336 memcpy(&nomemmsg[msgoffset), trace, tagSize);|| 337 mebStack->errorFunc(nomemmsg, mebStack->parm); 338 return ; 339 340 return stor; 341 } 342 343 * A wrapper around the system calloc routine to allocate an initialized 344 * array of elements, the wrapper checks for a 345 * 0-pointer return and calls the current memory error function on 346 allocation failure. 347 * @param count the number of array elements to allocate 348 * @param size the size of each array element 349 * @param trace the caller trace message 350 * @return a pointer to the allocated array; the memory allocated 351 is initialized to zero; if allocation fails and the current 352 memory error function returns, the O-pointer is returned 353 to the caller 354 355 void * 350 cAlloc(unsigned count, unsigned size, char *trace) 357 { 358 char *stor; 359 if ((stor = (void *)calloc(count, size)) == 0) 360 { 361 memcpy(&nomemmsg[msgoffset), trace, tagSize); 362 mebStack->errorFunc(nomemmsg, mebStack->parm); 363 return ; 364 } 365 return stor; 366 } 367 void * 368 reAlloc(void area, unsigned size, char *trace) 369 { 370 char *stori 371 if ((stor = (char *) realloc(area, size)) == B) 372 { 373 memcpy(&nomemmsg[msgoffset), trace, tagSize); 374 mebStack->errorFunc(nomemmsg, mebStack->parm); 375 return; 376 > 377 return stor; 378 } 379 void 380 mfree(void *area, char *trace) 381 { 382 if (area != 0) 383 { 384 free (area);

C Memory > mFree (area, trace) 370 char stor; 371 if ((stor = (char *)realloc(area, size)) == B) 372 { 373 memcpy(&nomemmsg[msgoffset), trace, tagSize); 374 mebStack->errorFunc(nomemmsg, mebStack->parm); 375 return; 376 } 377 return stor; 378 > 379 void 380 mFree (void *area, char *trace) 381 { 382 if (area ! ) 383 { { 384 free area); 385 } 386 else 387 { 388 memcpy(&zeromsg[msgOffset), trace, tagSize); 389 mebStack->errorFunc(zeromsg, mebStack->parm); 390 } 391} 392 #endit 393

1 h Memory No Selection #ifndef MEMORY_INCLUDE_GUARD 2 #define MEMORY_INCLUDE_GUARD 3 4 #ifdef MEMORY_EXPORT 5 #define MEMORY_API 6 #else 7 #define MEMORY_API extern & #endit 9 #ifndef NO MEMORY 10 typedef void (MemoryErrorFunc) (char *, void *); 11 MEMORY_API void pushMemoryErrorFunction(MemoryErrorFunc fnc, void *prm) 12 MEMORY_API void popMemoryErrorFunction(void); 13 MEMORY_API void *cAlloc(unsigned count, unsigned size, char *trace); 14 MEMORY_API void *reAlloc(void *area, unsigned size, char *trace); 15 MEMORY_API void #malloc(unsigned size, char *trace); 16 MEMORY_API void mFree(void *area, char *trace); 17 MEMORY_API void *cAllocT (unsigned count, unsigned size, char *trace); 18 MEMORY_API void *reAllocT(void *area, unsigned size, char *trace); 19 MEMORY_API void *malloc(unsigned size, char *trace); 20 MEMORY_API void mFreeT(void *area, char *trace); #else 22 #include <stdlib.h> #define malloc(s, t) malloc(s) 24 #define cAlloclc,s,t) calloc(c,s) 25 #define realloc(m, s, t) realloc(m, s) 26 #define mFree(m, t) free(m) 27 #endir 28 #ifdef MEMORY TRACKX #define malloc mallocT 30 #define cAlloc cAllocT #define reAlloc reAlloc 32 #define mFree mFree 33 #endir 34 MEMORY_API void trakReport(char *id); #undef MEMORY API 36 #end if 21 23 29 31 35 37