简体   繁体   English

strcpy给出分段错误

[英]strcpy giving segmentation fault

Consider the following code: 考虑以下代码:

#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;
}

I wanted to concatenate a cahracter and an string, But we don't have the function to do that, So I've defined a function chartoStr. 我想连接一个cahracter和一个字符串,但是我们没有执行此操作的函数,所以我定义了一个chartoStr函数。 Also c_exp and expressions varaibles aren't in read only mode, But strcpy() gives me segmentation fault. 同样,c_exp和表达式变量也不处于只读模式,但是strcpy()给了我分段错误。 I also tried other functions any way, Like strcat, Which didn't help. 我也以任何方式尝试了其他功能,例如strcat,但没有帮助。

In case it helps, I debug it in VS Code. 如果有帮助,我可以在VS Code中对其进行调试。 It opens strcpy-sse2-unaligned.S and shows segmentation fault in one of it's lines. 它打开strcpy-sse2-unaligned.S并在其中一行显示分段错误。

Is launch.json or task.json files needed? 是否需要launch.json或task.json文件? I don't think they may help, So I don't full the question with codes, But tell me if they're needed. 我认为它们可能无济于事,所以我没有用代码来补充问题,但请告诉我是否需要它们。

chartoStr() returns a local that is no longer available at function's end as well answered by @kiran Biradar chartoStr()返回一个在函数末尾不再可用的本地,并由@kiran Biradar回答

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

An alternative to calling chartoStr() it to create the string in the calling code using a compound literal (Since C99). 调用chartoStr()一种替代方法,以使用复合文字 (在C99起)在调用代码中创建字符串

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

A nice attribute is that there is no expensive allocation nor pointer to free. 一个不错的属性是,没有昂贵的分配,也没有免费的指针。 The compound literal is valid until the end of the block. 复合文字在块的末尾之前一直有效。


Note that code could employ other improvements by saving the length size_t len = strlen(c_exp) once early in cexpGen() and using it to append. 请注意,代码可以通过在cexpGen() size_t len = strlen(c_exp)一次size_t len = strlen(c_exp)的长度并使用它来追加来进行其他改进。

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

Other Problems 其他问题

Take heed to @alk about char c_exp[] = "1"; 注意@alk关于char c_exp[] = "1";

while (c_exp[strlen(c_exp) - 1]) > 10 is undefined behavior should strlen(c_exp) return 0. Perhaps while ((len = strlen(c_exp)) > 0 && c_exp[len - 1]) > 10 ? 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) is always true. if (now = 1)始终为true。 @user3386109 @ user3386109

You are getting segfault because you are returning address of local variable. 因为您正在返回局部变量的地址,所以您遇到段错误。

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

s will be destroyed once control exits chartoStr function. 一旦控件退出chartoStr函数, s将被销毁。

Compiler is also warning the same 编译器也警告同样

warning: function returns address of local variable [-Wreturn-local-addr] 警告:函数返回本地变量[-Wreturn-local-addr]的地址

  return s; ^ 

You don't need strcpy to copy the single character you can directly assign. 您不需要strcpy复制可以直接分配的单个字符。

To solve your problem you can try as below. 要解决您的问题,您可以尝试以下操作。

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

Don't forget to free s after work done. 不要忘记释放s工作完成之后。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM