HW3 Key

CS 321 Homework, Dr. Lawlor, 2006/03/07

Hint: read the lecture notes.  You'll have to add the correct "#include" line for each problem.
  1. Name as "321_HW3_1".  Make this program respond to the segfault signal by calling the mySignalHandler routine.
    #include <signal.h>
    /* Call this routine when a signal happens */
    void mySignalHandler(int signal_number)
    {
    printf("mySignalHandler> hit signal %d! OK!\n",signal_number);
    exit(1);
    }

    int foo(void) {
    int *badPointer=(int *)0;
    signal(SIGSEGV,mySignalHandler);
    printf("Now segfaulting (should call mySignalHandler)\n");
    (*badPointer)=0;
    printf("Back from segfault?!\n");
    return 0;
    }

  2. Name as "321_HW3_2".  Make this program NOT give a segfault, by mapping in read/write memory at the bad address in the "notSoBad" routine. You'll have to use the UNIX interfaces to do this.
    #include <sys/mman.h>
    /* Puts some memory at this pointer */
    void notSoBad(void *ptr)
    {
    void *ret=mmap(ptr,1024*1024, PROT_READ+PROT_WRITE, MAP_FIXED+MAP_ANON+MAP_SHARED, 0,0);
    }

    /* You may NOT change the foo routine! */
    int foo(void) {
    int *badPointer=(int *)0;
    notSoBad(badPointer); /* Put memory at the bad pointer */
    printf("Now accessing the pointer %p\n",badPointer);
    (*badPointer)=0;
    printf("I guess that's an OK pointer!\n");
    return 0;
    }

  3. Name as "321_HW3_3".  This program runs out of memory, but it only ever uses about 60MB of memory, and NetRun lets you use 100MB.  Fix the allocateBufs routine to not run out of memory. It may help to read this new lecture note on fragmentation. There are lots of other ways to do this, including:
    #include <new> /* needed for placement new */
    /* One linked-list node. Points to an allocated buffer */
    struct llNode {
    llNode *next; /* Points to next entry in the linked list */
    char *buf; /* allocated buffer */
    /* Constructor: create a linked-list node */
    llNode(llNode *next_,char *buf_)
    :next(next_), buf(buf_) {}
    /* Return number of nodes in linked list */
    int count(void) {if (next) return 1+next->count(); else return 1;}
    /* Free all the allocated buffers in this list */
    void freeBuf(void) {
    delete[] buf; buf=0;
    if (next) next->freeBuf();
    }
    };

    /* Allocate number different buffers of this size.
    Return a linked list of the allocated buffers. */
    llNode *allocateBufs(int size,int number) {
    llNode *head=NULL;
    char *nodeStorage=new char[sizeof(llNode)*number];
    for (int i=0;i<number;i++) {
    char *buf=new char[size];
    llNode *n=new(nodeStorage) llNode(head,buf); /* placement new */
    nodeStorage+=sizeof(llNode); /* skip over n's space */
    head=n;
    if ((i%100)==0)
    printf("Allocated %dth %d bytes at %p, link at %p\n",
    i,size,buf,n);
    }
    return head;
    }

    /* Use the buffers, then throw them away. */
    void processBufs(llNode *l,int size) {
    llNode *cur=l;
    while (cur!=0) {
    cur->buf[size-1]='K';
    cur=cur->next;
    }
    l->freeBuf();
    }

    /* You MAY NOT modify the foo routine... */
    int foo(void) {
    int nLinks=0;

    try {
    llNode *lA=allocateBufs(60000,1000);
    processBufs(lA,60000);
    llNode *lB=allocateBufs(61000,1000);
    processBufs(lB,61000);
    nLinks=lA->count()+lB->count();
    /* don't worry about throwing away the lA and lB links... */
    } catch (...) {
    printf("Error allocating memory!\n");
    }
    return nLinks;
    }