strcpy дает ошибку сегментации - PullRequest
0 голосов
/ 19 сентября 2018

Рассмотрим следующий код:

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

char *cexpGen();
char *chartoStr(char c);

char c_exp[] = "1";
char expressions[2] = {'+', '-'};

int main()
{
    cexpGen();
    printf("%s", c_exp);
    return 0;
}

char *cexpGen()
{
    int now = 1;
    while ((c_exp[strlen(c_exp) - 1]) > 10)
    {
        if ((c_exp[strlen(c_exp) - 1]) == '+' || (c_exp[strlen(c_exp) - 1]) == '-')
        {
            strcpy(c_exp, chartoStr(((c_exp[strlen(c_exp) - 2]) + 1)));
            continue;
        }

        if (now = 1)
        {
            strcpy(c_exp, chartoStr(expressions[0]));
            now++;
            cexpGen();
        }

        if (now = 2)
        {
            strcpy(c_exp, chartoStr(expressions[1]));
            now++;
            cexpGen();
        }

        if (now = 3)
        {
            strcpy(c_exp, chartoStr(((c_exp[strlen(c_exp) - 1]) + 1)));
        }
    }
}

char *chartoStr(char c)
{
    char s[2] = {c, '\0'};
    return s;
}

Я хотел объединить символ и строку, но у нас нет функции для этого, поэтому я определил функцию chartoStr.Также c_exp и выражения varaibles не находятся в режиме только для чтения, но strcpy () вызывает ошибку сегментации.Я также пробовал другие функции в любом случае, как strcat, который не помог.

Если это поможет, я отлаживаю его в VS Code.Он открывает strcpy-sse2-unaligned.S и показывает ошибку сегментации в одной из своих строк.

Нужны ли файлы launch.json или task.json?Я не думаю, что они могут помочь, поэтому я не наполняю вопрос кодами, но скажите, нужны ли они.

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

chartoStr() возвращает локальный номер, который больше не доступен в конце функции, а также отвечает @ kiran Biradar

char s[2] = {c, '\0'};
return s;  // bad, UB

Альтернатива вызову chartoStr() itдля создания строки в коде вызова с использованием составного литерала (начиная с C99).

// strcpy(c_exp, chartoStr(expressions[0]));
//            v-----------------------------v---- compound literal         
strcpy(c_exp, (char []){expressions[0], '\0'});

Приятным атрибутом является то, что нет дорогостоящего выделения или указателячтобы бесплатно.Составной литерал действителен до конца блока.


Обратите внимание, что код может использовать другие улучшения, сохранив длину size_t len = strlen(c_exp) один раз в начале cexpGen() и используя ее

// strcpy(c_exp, chartoStr(expressions[0]));
c_exp[len++] = expressions[0];
c_exp[len] = '\0';

Другие проблемы

Обратите внимание на @ alk о char c_exp[] = "1";

while (c_exp[strlen(c_exp) - 1]) > 10 - это неопределенное поведение должно strlen(c_exp) вернуть 0. Возможно while ((len = strlen(c_exp)) > 0 && c_exp[len - 1]) > 10?

if (now = 1) всегда верно. @ user3386109

0 голосов
/ 19 сентября 2018

Вы получаете segfault, потому что возвращаете адрес локальной переменной.

char s[2] = {c, '\0'};
    return s;

s будет уничтожено после выхода из функции управления chartoStr.

Компилятор также предупреждаетто же самое

предупреждение: функция возвращает адрес локальной переменной [-Wreturn-local-addr]

 return s;
 ^

Вам не нужно strcpy для копирования одногосимвол, который вы можете непосредственно назначить.

Чтобы решить вашу проблему, вы можете попробовать, как показано ниже.

char *chartoStr(char c)
{
    char *s = malloc(2);
     s[0] = c;
     s[1] =  '\0';
    return s;
}

Не забудьте освободить s после выполненной работы.

...