strcpy 给出分段错误

strcpy giving segmentation fault

考虑以下代码:

#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, '[=10=]'};
    return s;
}

我想连接一个字符和一个字符串,但是我们没有这样做的函数,所以我定义了一个函数 chartoStr。另外 c_exp 和表达式变量不是只读模式,但是 strcpy() 给我分段错误。我也以任何方式尝试了其他功能,比如 strcat,但没有帮助。

如果有帮助,我会在 VS Code 中调试它。它打开 strcpy-sse2-unaligned.S 并在其中一行中显示分段错误。

是否需要 launch.json 或 task.json 个文件?我不认为他们可能有帮助,所以我没有用代码来解决这个问题,但是如果需要的话请告诉我。

您遇到了段错误,因为您正在返回局部变量的地址。

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

s 将在控制退出 chartoStr 函数后销毁。

编译器也发出同样的警告

warning: function returns address of local variable [-Wreturn-local-addr]

 return s;
 ^

您不需要strcpy复制您可以直接分配的单个字符。

要解决您的问题,您可以尝试以下方法。

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

工作完成后别忘了释放 s

chartoStr() returns 一个在函数结束时不再可用的局部变量,由

回答
char s[2] = {c, '[=10=]'};
return s;  // bad, UB

调用 chartoStr() 的替代方法是使用 compound literal(自 C99 起)在调用代码中创建 字符串

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

一个不错的特性是没有昂贵的分配,也没有指向空闲的指针。 复合文字在块结束前有效。


请注意,代码可以通过在 cexpGen() 早期保存一次长度 size_t len = strlen(c_exp) 并使用它来追加来进行其他改进。

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

其他问题

注意关于char c_exp[] = "1";

while (c_exp[strlen(c_exp) - 1]) > 10 未定义的行为 应该 strlen(c_exp) return 0。也许 while ((len = strlen(c_exp)) > 0 && c_exp[len - 1]) > 10?

if (now = 1) 始终为真。