C - Ошибка сегментации в strcpy()

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

char *vStrs[] = {"Max", "Moritz", "Bolte", "Hans Huckebein", "Helene", "Antonius", "Boeck", "Maecke", "Lempel", "Schlich"};

int main()
{
    int num = sizeof(vStrs) / sizeof(vStrs[0]);
    int len = sizeof(vStrs[0]);
    char exchnge[len];
    char vBuf[128];
    char *ndata;
    int i, j;

    for(i=0; i<num-1; i++)
    {
        for(j=i+1; j<num; j++)
        {
            if(strcmp(vStrs[j], vStrs[i]) < 0)
            {
                strcpy(exchnge, vStrs[j]);
                strcpy(vStrs[j], vStrs[i]);
                strcpy(vStrs[i], exchnge);
            }
        }
    }

    for(i=0; i<num; i++)
        printf("%s\n", vStrs[i]);

    return 0;
}

Привет ребят,

Кто-нибудь знает, почему я получаю ошибку сегментации на линии strcpy(vStrs[j], vStrs[i]);?

У меня есть массив строк и хочу его отсортировать. Но я получаю ошибку сегментации. Функция strcpy() выше, которая работает. Что случилось?

Наверное, это очевидно, но я не понимаю.

Спасибо!

2 ответа

Решение

С strcpy(vStrs[j], vStrs[i])вы копируете содержимое строкового литерала в другой строковый литерал. Это так же, как если бы вы написали strcpy("Max","Moritz"), но строковые литералы не должны быть изменены (его неопределенное поведение).

В любом случае, цель вашей программы - обмен указателями на содержимое, а не на содержание как таковое. Так что если вы измените программу следующим образом, все должно быть в порядке:

char *vStrs[] = {"Max", "Moritz", "Bolte", "Hans Huckebein", "Helene", "Antonius", "Boeck", "Maecke", "Lempel", "Schlich"};

int main()
{
    int num = sizeof(vStrs) / sizeof(vStrs[0]);

    for(int i=0; i<num-1; i++)
    {
        for(int j=i+1; j<num; j++)
        {
            if(strcmp(vStrs[j], vStrs[i]) < 0)
            {
                char *exchnge = vStrs[j];
                vStrs[j] = vStrs[i];
                vStrs[i] =exchnge;
            }
        }
    }

    for(int i=0; i<num; i++)
        printf("%s\n", vStrs[i]);

    return 0;
}

... потому что вы не запускали свой компилятор в самом строгом из возможных режимов проверки ошибок.

Некоторые люди считают, что -Wall означает "все предупреждения". Это не так. Даже не -Wall -Wextra даже приближается к "строжайшему из возможных режимов проверки ошибок". Я бы начал с -Wall -Wextra -pedantic -Wmissing-include-dirs -Wfloat-equal -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wmissing-declarations -Wredundant-decls -Wshadow -Wno-system-headers -Wno-deprecated -Wunused-variable -Wunused-parameter -Wunused-function -Wunused, а затем обратитесь к руководству, чтобы узнать, может ли ваш компилятор сделать больше для вас.

Адаптируйте этот последний абзац к выбранному вами компилятору, если вы не используете GCC. Компилятор - ваш друг, дайте ему любую возможность, чтобы вы не допустили ошибок.

С этими опциями вы получите следующее предупреждение:

предупреждение: инициализация отбрасывает спецификатор const из целевого типа указателя [-Wdiscarded-qualifiers]

Потому что это то, что происходит: "Max" имеет тип char * что касается стандарта языка, но - как строковый литерал - указанная память не записывается. Вот почему ваш strcpy() segfaults на вашей машине. С -Wwrite-stringsвы указываете компилятору вместо этого делать строковые литералы char const * (как и при использовании C++), позволяя компилятору генерировать предупреждение, когда вы игнорируете не-записываемый характер литерала.

Предупреждения компилятора. Не выходи из дома без них.

Другие вопросы по тегам