2017-01-18 3 views
0

Я понимаю, что ошибка сегментации указывает, что я пытаюсь получить доступ к памяти, которую я не должен/не был выделен, но не могу найти, что вызывает эту ошибку в моем коде. Другие ответы указывают на использование Valgrind, но у меня нет компилятора на локальной машине и у меня нет прав администратора, чтобы установить его на Школьном сервере. Любая помощь, указывающая, где произошла ошибка, будет с большой благодарностью. Вот заголовочный файлОтслеживание ошибки сегментации 11

/* 
* File:  set.h 
* 
* Copyright: 2015, Darren C. Atkinson 
* 
* Description: This file contains the public function and type 
*    declarations for a set abstract data type for strings. A 
*    set is an unordered collection of distinct elements. 
* 
*    Note that this file uses the bool type, but does not define 
*    it. You should include <stdbool.h> beforehand. 
*/ 

# ifndef SET_H 
# define SET_H 

typedef struct set 
{ 
    char **elts; //char * array containing strings 
    int length; //total length of array 
    int size; //number of strings within array 
}SET; 


SET *createSet(int maxElts); 

void destroySet(SET *sp); 

int numElements(SET *sp); 

bool hasElement(SET *sp, char *elt); 

bool addElement(SET *sp, char *elt); 

bool removeElement(SET *sp, char *elt); 

# endif /* SET_H */ 

Данный тестовый файл для компиляции с моим кодом.

/* 
* File:  unique.c 
* 
* Copyright: 2015, Darren C. Atkinson 
* 
* Description: This file contains the main function for testing a set 
*    abstract data type for strings. 
* 
*    The program takes two files as command line arguments, the 
*    second of which is optional. All words in the first file 
*    are inserted into the set and the counts of total words and 
*    total words in the set are printed. If the second file is 
*    given then all words in the second file are deleted from 
*    the set and the count printed. 
*/ 

# include <stdio.h> 
# include <stdlib.h> 
# include <string.h> 
# include <stdbool.h> 
# include "set.h" 


/* This is sufficient for the test cases in /scratch/coen12. */ 

# define MAX_SIZE 18000 


/* 
* Function: main 
* 
* Description: Driver function for the test application. 
*/ 

int main(int argc, char *argv[]) 
{ 
    FILE *fp; 
    char buffer[BUFSIZ]; 
    SET *unique; 
    int words; 


    /* Check usage and open the first file. */ 

    if (argc == 1 || argc > 3) { 
     fprintf(stderr, "usage: %s file1 [file2]\n", argv[0]); 
     exit(EXIT_FAILURE); 
    } 

    if ((fp = fopen(argv[1], "r")) == NULL) { 
     fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]); 
     exit(EXIT_FAILURE); 
    } 


    /* Insert all words into the set. */ 

    words = 0; 
    unique = createSet(MAX_SIZE); 

    while (fscanf(fp, "%s", buffer) == 1) { 
     words ++; 
     addElement(unique, buffer); 
    } 

    printf("%d total words\n", words); 
    printf("%d distinct words\n", numElements(unique)); 
    fclose(fp); 


    /* Try to open the second file. */ 

    if (argc == 3) { 
     if ((fp = fopen(argv[2], "r")) == NULL) { 
      fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[2]); 
      exit(EXIT_FAILURE); 
     } 


     /* Delete all words in the second file. */ 

     while (fscanf(fp, "%s", buffer) == 1) 
      removeElement(unique, buffer); 

     printf("%d remaining words\n", numElements(unique)); 
    } 

    destroySet(unique); 
    exit(EXIT_SUCCESS); 
} 

И, наконец, мой код, из которого исходит ошибка.

/* 
* File:  unsorted.c 
* 
* 
* Description: This file contains the definitions for a simple interface for a SET structure that contains a list of strings as well as the list size. 
*/ 
#include <assert.h> 
#include <stdbool.h> 
#include <string.h> 
#include <stdlib.h> 
#include "set.h" 

int findElement(SET *sp,char *elt); 

struct SET 
{ 
    char **elts; //char * array containing strings 
    int length; //total length of array 
    int size; //number of strings within array 
}; 

//initializes SET 
//O(1) efficiancy 
SET *createSet(int maxElts) 
{ 
    SET *sp; 
    sp->elts = (char **) malloc(sizeof(char*)*maxElts); 
    assert(sp->elts!=NULL); 
    sp->size = 0; 
    sp->length = maxElts; 
    return sp; 
} 

//frees all strings from memory and then the containing array 
//O(n) efficiancy n==sp->size 
void destroySet(SET *sp) 
{ 
    while (sp->size > 0) free(sp->elts[--sp->size]); 
    free(sp->elts); 
} 

//return the number of strings within the array 
//O(1) efficiency 
int numElements(SET *sp) 
{ 
    return sp->size; 
} 

//Sequentially searches SET for elt and return the array location, if not found -1 is returned 
//O(n) efficiency n=sp->size 
int findElement(SET *sp,char *elt) 
{ 
    int i =0; 
    for (i; i < sp->size; i++) 
    { 
     if (strcmp(sp->elts[i],elt) == 0) return i; 
    } 
    return -1; 
} 

//appends elt on the end of the array within SET 
//O(1) efficiency 
bool addElement(SET *sp, char *elt) 
{ 
    if (findElement(sp, elt) != -1) return false; 
    if (sp->size == sp->length) return false; 
    sp->elts[sp->size] = (char*) malloc(sizeof(char)*(strlen(elt)+1)); 
    assert(sp->elts[sp->size]!=NULL); 
    sp->size = sp->size +1; 
    return true; 
} 

//returns true if SET contains elt otherwise return false 
//O(n) efficiency n=sp->size 
bool hasElement(SET *sp, char *elt) 
{ 
    if (findElement(sp,elt) == -1) return true; 
    return false; 
} 

//finds elt and removes it from array if present, then moves all following strings forward in the array 
//O(n) efficiency n=sp->size 
bool removeElement(SET *sp,char *elt) 
{ 
    int loc = findElement(sp,elt); 
    if (loc == -1) return false; 
    free(sp->elts[loc]); 
    while (loc <sp->size) 
    { 
     sp->elts[loc] = sp->elts[loc+1]; 
     loc++; 
    } 
    sp->size=sp->size-1; 
    return true; 
} 
+1

Вы должны, вероятно, фигурировать как установить компилятор (вы, возможно, уже есть) и Valgrind. – synchronizer

+2

Если у вас есть только возможности для компиляции и выполнения, на которые можно положиться, вы можете попытаться сократить время от времени на выполнение своей программы, чтобы уменьшить ее до наименьшей возможной программы, которая обнаруживает проблему. Зачастую это упражнение поможет вам разобраться в природе проблемы, но даже если это не так, результатом будет именно тот вид [mcve], который мы ищем здесь. –

+1

С '(fscanf (fp,"% s ", buffer)', почему бы не ограничивать '(fscanf (fp,"% XXXs ", buffer)' или что-то вроде 'BUFISZE -1' может быть? – chux

ответ

0

в функции: createSet(),

переменная зр не инициализирован, чтобы указывать на экземпляр набора структуры.

так что код должен быть похож на это:

SET *sp = NULL; 
if(NULL == (sp = malloc(sizeof(struct set))) 
{ 
    perror("malloc for struct set failed"); 
    exit(EXIT_FAILURE); 
} 

В противном случае зр будет содержать какие-либо случайный адрес в стеке на это место.

Это неопределенное поведение и может привести к неисправности события сегментный

+0

Это какой-то неясный код. Любая причина, по которой вы не будете писать 'SET * sp = malloc (...); if (sp == NULL) {... '? – Lundin

+0

@ Lundin, этот вид утверждения очень часто используется, и он помогает запретить последующим сопровождениям кода отделять выделение от проверки ошибок. – user3629249

+0

Нет, он обычно не используется. И нет причин, по которым вы хотели бы сохранить смещение распределения и ошибок в одном выражении. Если вы написали 'SET * sp = malloc (...); if (sp == NULL) ', а затем некоторые замедляют принятие решения о добавлении кода ветвления между этими двумя утверждениями, вы ничего не можете сделать, чтобы помочь им, потому что они слишком некомпетентны, чтобы поддерживать код C в первую очередь. Нет причин для запутывания вашего кода только потому, что вы подозреваете, что некомпетентные люди его поддержат.Вместо этого предположите, что ваш код будет поддерживаться компетентными программистами C. – Lundin

Смежные вопросы