Ошибка сегментации (ядро сброшено) Ошибка в программе C с динамическими массивами c - PullRequest
1 голос
/ 02 марта 2020

Я не могу понять, откуда происходит эта ошибка, но я предполагаю, что это как-то связано с выделением массивов / передачей массивов в качестве параметров. Извиняюсь, я новичок в C. Если бы кто-то мог помочь мне выяснить, откуда возникла эта ошибка, это было бы чрезвычайно полезно.

#include <stdio.h>
#include <stdlib.h>


void getSize(int *sizePtr) {
    printf("Please enter the size of the class: ");
    scanf("%i", sizePtr);
}

void allocateMemory(float *scoresPtr, int size) {
    scoresPtr = malloc(size * (sizeof(float)));
}

void readScores(float *scores, int size) {
    int i;
    printf("Enter each score as a floating point value, each on a separate line, followed by enter: \n");
    for (i = 0; i < size; i++) {
        scanf("%f", &scores[i]);
    }
}

void makeArrayCopy(float *original, float *copy, int size) {
    int j;
    for (j = 0; j < size; j++) {
        copy[j] = original[j];
    }
}

void findMin(float *scores, int size) {
    int min = scores[0];
    int i;

    for (i = 1; i < size; i++) {
        if (scores[i] < min) {
            min = scores[i];
        }
    }
    printf("%.1f", min);
}

void findMax(float *scores, int size) {
    int max = scores[0];
    int i;

    for (i = 1; i < size; i++) {
        if (scores[i] > max) {
            max = scores[i];
        }
    }
    printf("%.1f", max);
}


void findSum(float *scores, int size) {
    int i;
    int sum = 0;

    for (i = 0; i < size; i++) {
        sum += scores[i];
    }

    printf("%.1f", sum);
}

void findMean(float *scores, int size) {
    int i;
    double mean = 0;

    for (i = 0; i < size; i++) {
        mean += scores[i];
    }

    mean /= size;
    mean = (float)mean;
    printf("%.1f", mean);
}

void findMedian(float *sortedScores, int size) {
    int mod = size % 2;
    int sizeDivTwo = size / 2;
    float median;

    if (mod = 0) {
        median = (sortedScores[sizeDivTwo] + sortedScores[sizeDivTwo + 1]) / 2;
    } else {
        median = sortedScores[sizeDivTwo + 1];
    }
    printf("%.1f", median);
}

void printAllScores(float *scores, int size) {
    int i;
    printf("%s", "Class Scores: \n");

    for (i = 0; i < size; i++) {
        printf("%.1f", scores[i]);
        printf("%c", "\n");
    }
}

void sortAscending(float *scores, int size) {
    int i, j;
    float temp;

    for (i = 0; i < size;  i++) {
        for (j = 0;  j < size - 1; j++) {
            if (scores[j] > scores[j + 1]) {
                temp = scores[j];
                scores[j] = scores[j+1];
                scores[j + 1] = temp;
            }
        }
    }
}




int main() {
    float scores;
    int size;
    float sortedCopy;
    int op;

    getSize(&size);
    allocateMemory(&scores, size);
    readScores(&scores, size);

    allocateMemory(&sortedCopy, size);
    makeArrayCopy(&scores, &sortedCopy, size);
    sortAscending(&sortedCopy, size);


    while (op != 0) {
        printf("%s", "Please choose an option: \n 1: Calculate sum \n 2: Calculate mean \n 3: Calculate median \n 4: Find minimum score \n 5: Find maximum score \n 6: Print all scores \n 7: Print all scores in ascending order \n8: Exit");
        scanf("%i", op);

        switch(op) {
            case 1:
                findSum(&scores, size);
                break;
            case 2:
                findMean(&scores, size);
                break;
            case 3: 
                findMedian(&sortedCopy, size);
                break;
            case 4: 
                findMin(&scores, size)
                break;
            case 5: 
                findMax(&scores, size);
                break;
            case 6:
                printAllScores(&scores, size);
                break;
            case 7:
                printAllScores(&sortedCopy, size);
                break;
            case 8:
                op = 0;
                break;
        }
    }   

}

Ответы [ 3 ]

0 голосов
/ 02 марта 2020

Начните с использования gdb с "gdb a.out" (или именем вашей скомпилированной программы)

(gdb) start
Temporary breakpoint 1 at 0xd0f
Starting program: a.out 

Temporary breakpoint 1, 0x0000555555554d0f in main ()
(gdb) next
Single stepping until exit from function main,
which has no line number information.
Please enter the size of the class: 5
Enter each score as a floating point value, each on a 
separate line, followed by enter: 
4.5
4.7
4.7
4.6
4.8

Программа получила сигнал SIGSEGV, Ошибка сегментации. 0x00005555555548a8 в makeArrayCopy ()

Затем добавьте printf ("size =% d \ n", size); to makeArrayCopy (до l oop):

Please enter the size of the class: 3
Enter each score as a floating point value, each on a 
separate line, followed by enter: 
2.5
2.6
2.7
size = 1076258406

Вы быстро найдете решение, но вам будет еще полезнее понять, как работает GDB и как можно отлаживать

0 голосов
/ 02 марта 2020

Следующий код вызывает повреждение памяти.

...
scanf("%f", &scores[i]); // line 18, write to the outside of scores. 
...
float scores; // line 116
...

Ниже сообщается об ошибке. ссылка для воспроизведения этой ошибки.

=========== Начало # 0 сообщения времени выполнения stensal ===========

Ошибка времени выполнения: [запись в за пределами пространства памяти] Продолжение выполнения может вызвать неопределенное поведение, прервать!

-
- Writing 4 bytes to 0xffc067d0 will clobber the adjacent data.
-
- The memory-space-to-be-written (start:0xffc067cc, size:4 bytes) is bound to 'scores' at
-     file:/prog.c::116, 9
-
-  0xffc067cc               0xffc067cf
-  +------------------------------+
-  |the memory-space-to-be-written|......
-  +------------------------------+
-                                  ^~~~~~~~~~
-        the write starts at 0xffc067d0 that is right after the memory-space end.
-
- Stack trace (most recent call first) of the write.
- [0]  file:/musl-1.1.10/src/stdio/vfscanf.c::302, 5
- [1]  file:/musl-1.1.10/src/stdio/vscanf.c::7, 9
- [2]  file:/musl-1.1.10/src/stdio/scanf.c::25, 8
- [3]  file:/prog.c::18, 5
- [4]  file:/prog.c::123, 3
- [5]  [libc-start-main]
-

============ Конечное # 0 сообщение времени выполнения stensal === =========

0 голосов
/ 02 марта 2020

У вас здесь немало проблем.

Во-первых, вы должны инициализировать значения, такие как op, в противном случае сравнение op != 0 не определено. Кроме того, вы передаете op на scanf() вместо его адреса.

Непосредственной причиной вашей проблемы является то, что вы используете указатели для размещения переменных для выделения памяти с использованием malloc.

В ваших findMin(), findMax(), findSum() вы используете тип данных int для соответствующих значений, в то время как вы должны использовать float.

Правки ниже должно помочь (, а также включение предупреждений для вашего компилятора )

// in main() 
float *scores;
float *sortedCopy;
int   op = -1;

// remove & from before scores and sorted copy in all other function calls
allocateMemory(&scores, size);
allocateMemory(&sortedCopy, size);

// in the while loop
scanf("%d", &op);

// at the end of main(), don't forget to free mem
free(scores);
free(sortedCopy);

// in allocateMemory
void allocateMemory(float **scoresPtr, int size) { 
    *scoresPtr = malloc(size * (sizeof(float))); 
}

// in findMedian()

if (mod == 0) { // == is for comparison, = is for assignment
...