在 C 中创建一个 StartsWith 函数得到 "Segmentation fault",有什么问题吗?

Make a StartsWith function in C getting "Segmentation fault", What's wrong?

我正在尝试制作一个 startswith 函数,如果我有一个字符串包含
"Hello I am kira"
会拆分成第一个字
"Hello"

而且我真的尽了最大努力把它弄成这个形式

#include <stdio.h>
unsigned char *startswith(unsigned char *str)
{
    char *result;
    char *cstr = (char *)str;     
    for (int i=0; cstr[i] != ' '; i++)
       result[i] = cstr[i];
    return(result);
}

int main()
{
    printf("%s\n",startswith("What is your name momo?"));
    return 0;
}

应该打印 "in my imagination"

What

newline 然后用 0 退出 但是我在编译时遇到了未知的神圣错误

Segmentation fault

我不明白为什么会这样,甚至无法定位问题所在
gcc 没有帮助或显示警告

stdio.h header 只是打印结果而已
我知道有一种方法可以在不使用任何标准库的情况下实现这一点,但我需要 leading

谢谢!

result 中分配一些内存。 result=malloc(sizeof(char)*MAXLEN);

现在您正在访问存储在 result 中的一些垃圾值。

访问未初始化的变量是Undefined Behavior


  • 你也可以分配strlen(str)+1因为你知道不管结果是什么最多只要str.

  • $7.20.3.1 另一点是,您可以使用 calloc 函数,其中 space 被初始化为所有位 zero.This 的好处是始终有一个空终止字符串,即使您不小心省略了空终止1

1.由 David C. Rankin 指出

基本上你在这里做的是使用一个没有分配内存的指针。你需要使用 malloc 为结果变量分配内存,为此你需要包括 stdlib.h

#include <stdio.h>
#include<stdlib.h>
#define MAXLEN 1000
unsigned char *startswith(unsigned char *str)
{
    char *result = malloc(sizeof(char)*MAXLEN);
    char *cstr = (char *)str;     
    for (int i=0; cstr[i] != ' '; i++)
    result[i] = cstr[i];
    return(result);
}

int main()
{
    printf("%s\n",startswith("What is your name momo?"));
    return 0;
}

对这里发生的事情进行更深入的解释...您遇到了段错误,因为您正在取消引用指向您的进程不拥有的内存的指针。您的 char* result 指针未初始化,这意味着它可能包含任何类型的垃圾数据。当您尝试 result[i] = cstr[i] 时,您正在调用 undefined behavior(所以不会再让我 link 他们未定义的行为文档),这仅仅意味着从这一点开始程序的向前执行具有不可预测的结果。在您的情况下,UB 表现为段错误,尽管它可能并非总是如此。

为了初始化您的指针,您必须使用 malloc 或其类似函数之一为其分配一些 space。当你用完它时,你还应该 free 你的记忆。你的程序太短了,在这种情况下这没什么大不了的(OS 肯定会在进程退出时清理分配给进程的所有内存),但养成习惯是件好事。

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

// this function shouldn't modify str (and in fact modifying a string
// literal like you're passing in would be UB anyway), so make this
// a const char*
char *startswith(const char *str)
{
    // sizeof(char) is defined as 1 in the standard, so you can leave it out of the malloc expression
    char *result = malloc(strlen(str)+1);  // Assuming str has at least 1 space, this will guarantee enough space for result
    if (result == NULL)   // make sure malloc returned some memory for you
    {
        // handle the error here how you want
        fprintf(stderr, "out of memory!\n");
        exit(-1);
    }
    // no need for cstr
    int i;  // move i out of the loop so it will be in scope after the loop
    for (i=0; str[i] != ' '; i++)
       result[i] = str[i];
    // NUL terminate your string
    result[i] = '[=10=]';

    // "return" isn't a function, parenthesis unnecessary.
    return result;
}

int main(void)
{
    // store the returned result to a variable so we can free it
    char* result = startswith("What is your name momo?");
    printf("%s\n", result);
    // clean up the memory
    free(result);
    return 0;
}