0

I keep getting Segmentation Error: 11 after PrintDictionary is called. Any help would be much appreciated! As far as I know Segmentation Error: 11 means that I am trying to access somewhere in memory I am not allowed to access. But I simply cannot find that point in my code. I always get it after PrintDictionary is called and all the values are printed out.

//-----------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include"Dictionary.h"
#define MAX_LENGTH 200

// private types --------------------------------------------------------------

typedef struct NodeObj{
    char key[MAX_LENGTH];
    char value[MAX_LENGTH];
    struct NodeObj* next;
} NodeObj;

// Node
typedef NodeObj* Node;

// newNode()
// constructor of the Node type
Node newNode(char* k, char* v) {
    Node N = malloc(sizeof(NodeObj));
    assert(N!=NULL);
    strcpy(N->key, k);
    strcpy(N->value, v);
    N->next = NULL;
    return(N);
}

// freeNode()
// destructor for the Node type
void freeNode(Node* pN){

    if( pN!=NULL && *pN!=NULL ){
       free(*pN);
       *pN = NULL;
    }
}


// StackObj
typedef struct DictionaryObj{
   Node head;
   int numItems;
} DictionaryObj;


// public functions -----------------------------------------------------------

// newDictionary()
// constructor of the Dictionary type


Dictionary newDictionary(void){
   Dictionary D = malloc(sizeof(DictionaryObj));
   assert(D!=NULL);
   D->head = NULL;
   D->numItems = 0;
   return(D);
}

void freeDictionary(Dictionary* pD){
    if(isEmpty(*pD)==0) makeEmpty(*pD);
    if( pD!=NULL && *pD!=NULL ){
       free(*pD);
       *pD = NULL;
    }
}

// isEmpty()
// returns 1 (true) if S is empty, 0 (false) otherwise
// pre: none
int isEmpty(Dictionary D){
   if( D==NULL ){
      fprintf(stderr, 
              "Stack Error: calling isEmpty() on NULL Stack reference\n");
      exit(EXIT_FAILURE);
   }
   return(D->numItems==0);
}

// size()
//Returns size of the list
int size(Dictionary D) {
    return D->numItems;
}

//lookup()
//Searches the dicitonary for a key
char* lookup(Dictionary D, char* kee){
   Node N  = D->head;
   for(int i = 0; i < D->numItems; i++){ 

       if(strcmp(N->key, kee) == 0){

           return N->value;
       }
       else {

           N = N->next;

       }
   }
   return NULL;
}
//inserts a new node at the end if none exists
void insert(Dictionary D, char* kee, char* valu){

   if( D->head==NULL ){
      D->head = newNode(kee, valu);
       return;
   }
   if(lookup(D, kee) != NULL) {
       fprintf(stderr, "cannot insert duplicate keys\n");
       return;
   }    
    Node N = D->head;
    while(N->next != NULL) {
        N=N->next;
    }
   N->next = newNode(kee, valu);
   D->numItems++;
}

// deletes a value from the list
void delete(Dictionary D, char* kee){
   if( D==NULL ){
      fprintf(stderr, "Stack Error: calling delete() on NULL Stack reference\n");
      exit(EXIT_FAILURE);
   }
   if( D->numItems==0 ){
      fprintf(stderr, "Stack Error: calling delete() on empty Stack\n");
      exit(EXIT_FAILURE);
   }
   Node N = D->head;
   while(N!= NULL){
       if(strcmp(N->next->key, kee) == 0) {
           N->next = N->next->next;
           return;
       }
       else {
           N = N->next;
       }
   }
}


//erases the dictionary
void makeEmpty(Dictionary D){
   D->head = NULL;
   D->numItems = 0;
}

// printStack()
// prints a text representation of D to the file pointed to by out
// pre: none
void printDictionary(FILE* out, Dictionary D){
   Node N = D->head;
   while(N!=NULL) {
     fprintf(out, "%s %s\n ", N->key, N->value); 
     N=N->next; 
    printf("Test1\n");   
   }
}

int main(int argc, char* argv[]){
   Dictionary A = newDictionary();
   char* k;
   char* v;
   char* word1[] = {"1","2","3","4","5","6","7"};
   char* word2[] = {"a","b","c","d","e","f","g"};
   int i;
   for(i=0; i<7; i++){  //test insert
       printf("loop\n");
      insert(A, word1[i], word2[i]);
   }

   printDictionary(stdout, A); //test printDictionary
    printf("Print"); 

   //insert(A, "5", "z"); //errorThrown:cannot enter duplicate key.

   delete(A, "1");
   delete(A, "3");
   delete(A, "7");

   printDictionary(stdout, A); //show that they were deleted by printing

   for(i=0; i<7; i++){ // test lookup on pairs with keys that do and don't exist
      k = word1[i];
      v = lookup(A, k);
      printf("key=%s %s%s\n", k, (v==NULL?"not found ":"value="), v);
   }

   // delete(A, "0");  //errorThrown:cannot delete what doesnt exist
   // delete(A, "3");  //errorThrown:cannot delete what doesnt exist

   printf("%s\n", (isEmpty(A)?"isEmpty:true":"isEmpty:false"));//test isEmpty,    size, and makeEmpty
   printf("size:%d\n", size(A));
   makeEmpty(A);
   printf("%s\n", (isEmpty(A)?"isEmpty:true":"isEmpty:false"));

   freeDictionary(&A); //test freeDictionary

   return(EXIT_SUCCESS);
}
  • `valgrind` can help. BTW, it's a bad idea to hide the pointer types, it makes your code much less analyzable.. – Eugene Sh. Nov 10 '16 at 19:07
  • the debugger helps too! – Jean-François Fabre Nov 10 '16 at 19:08
  • As do trying to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) or a [Short, Self Contained, Correct (Compilable), Example](http://sscce.org). And [rubber duck debugging](https://en.wikipedia.org/wiki/Rubber_duck_debugging). – Some programmer dude Nov 10 '16 at 19:16
  • Your `delete` function can (and will) dereference a `NULL` pointer with `strcmp(N->next->key, kee)`. Likewise with `N->next = N->next->next`. Also, even if that is fixed, you never update `numItems` once you leak memory by orphaning the node being trimmed by `delete`, so a future `lookup` can likewise potentially dereference `NULL` – WhozCraig Nov 10 '16 at 19:18
  • So I put valgrind in my makefile and ran it, I received this error : make: valgrind: No such file or directory make: *** [check] Error 1" – Kennedy Bagnol Nov 10 '16 at 19:46
  • Not quite sure what you mean by "I put valgrind in my makefile and ran it". [Valgrind](http://valgrind.org/) is an analysis tool. Simply putting a "valgrind" target in your makefile (if that's what you did?) isn't going to do anything. You'll need to run your program in the valgrind framework and it will analyze your code. – yano Nov 10 '16 at 20:36

0 Answers0