【问题标题】:Segmentation fault in my strcpy我的 strcpy 中的分段错误
【发布时间】:2018-12-26 13:15:27
【问题描述】:

我正在编写自己的strcpy,因为string.h 中的默认值仅接受const char * 作为要从中复制的源字符串。 我正在尝试这个非常基本的原型(是的,返回没有意义,我只是在尝试):

int copyStrings(char * dest, char * source){
    int i=0;
    while(source[i]!='\0'){
        dest[i]=source[i];
        i++;
    }
    dest[i]='\0';
    return 0;
}

它在 gdb 中给我 SIGSEGV, Segmentation Fault 错误,在 dest[i]=source[i] 行,就在 first 字符处。我很确定 dest[i] 不是字符串文字,所以我应该能够修改它。

我做错了什么?

编辑:这是电话

int main(){
    char * str = (char*)malloc((int)sizeof(double));
    char * str2 = (char *)malloc((int)sizeof(int));
    str = "hello";
    str2 = "hey jude";
    copyStrings(str2, str);
    free(str);
    free(str2);
    return 0;
}

【问题讨论】:

  • 显示来电者。顺便说一句,它应该返回一些有意义的东西。
  • strcpy() 只接受const char * 有什么问题?您可以将非 const char * 传递给函数,该函数只是承诺它不会通过 const char * 更改数据。它没有害处;您可以将 const 或非 const 字符串作为第二个参数传递。
  • intdouble 的大小与字符串有什么关系?之后,您还可以为它们分配字符串文字。
  • 由于 malloc() 需要 size_t 参数,您的 (int)sizeof 的结果的强制转换是奇数。字符串"hey jude" 有 9 个字节长;在大多数机器上,sizeof(double)8(而 sizeof(int) 通常是 4)。这可能是麻烦的原因。您正在泄漏内存;而你 ARE 试图分配给常量(字符串文字)。您需要使用strcpy() 来分配"hello""hey jude" — 并且您需要确保有足够的空间将字符串复制到其中。提示:您没有分配足够的空间。将您的 sizeof() 操作数更改为 16。使用strcpy()复制。
  • 否:const char * 参数说“我,strcpy(),保证不会尝试修改作为我的第二个参数传递的字符串;我会读它,但我不会写信给它”。

标签: c string pointers char strcpy


【解决方案1】:

这是为str2 分配一个字符串文字——这正是你声称你没有做的事情。这实际上是您的段错误的原因。

str2 = "hey jude";

这也导致了内存泄漏,因为在此之前,您 malloc 分配了一些内存并将其分配给 str2。但是没有足够的内存来保存字符串。通常,int 是 4 个字节,您需要 9 个字节来存储该字符串。

您想要做的是,它分配与字符串中的字节数一样多的字节,加上一个额外的字节来存储末尾的 \0 终止字符。

str2 = malloc(strlen("hey jude")+1);
strcpy(str2,"hey jude");

或者在某些系统上,您可以使用 POSIX 函数 strdup(),它可以通过一个方便的函数调用有效地完成上述工作。

str2 = strdup("hey jude");

【讨论】:

  • 严格来说,当然,你应该检查malloc()的结果。目前这并不重要——原始代码中还有其他更大的问题。
  • 写入只读内存将导致 SIGSEV。这就是为什么您在 copyString 函数的第一行出现分段错误的原因:您将一个 litteral const 的地址分配给 str2,然后您尝试在其上复制 str
  • 这能解释为什么如果我在执行str2 = "hey jude"; 之后执行free(str2) 会出现段错误吗?因为我给它分配了一个文字?
  • @riciloma 是的,而且它不会释放你分配的内存,因为你已经覆盖了它
【解决方案2】:

让我们一行一行地去看看它哪里出错了:

int main(){
    char * str = (char*)malloc((int)sizeof(double));
    char * str2 = (char *)malloc((int)sizeof(int));
    str = "hello";
    str2 = "hey jude";
    copyStrings(str2, str);
    free(str);
    free(str2);
    return 0;
}

int main(){ - 这是main 的错误定义。应该是int main(int argc, char **argv)

char * str = (char*)malloc((int)sizeof(double)); - 定义str,然后分配(可能)8字节的内存并将其地址分配给strmalloc 接受 size_t 参数,因此转换 (int)sizeof(double) 不正确。此外,在 C 中,malloc 的返回值应该从不 被强制转换。所以这一行应该是char * str = malloc(sizeof(double));

char * str2 = (char *)malloc((int)sizeof(int)); - 与前一行相同的问题。应该是char *str2 = malloc(sizeof(int));

str = "hello"; - 导致内存泄漏,因为您之前刚刚分配的两行内存现在已经无法挽回地丢失了。这里有两个选择 - 要么在定义 str 时不分配内存,要么先释放它。让我们做后者:

free(str);
str = "hello";

str2 = "hey jude"; - 同样的问题,类似的解决方案:

free(str2);
str2 = "hey jude";

copyStrings(str2, str); - 在这里您告诉您的例程将常量字符串“hello”复制到常量字符串“hey jude”的顶部。这在在某些系统上可以正常工作,但会在在其他系统上崩溃。问题在于常量字符串“hey jude”的处理。如果它存储在可修改的内存中,代码就可以正常工作。但是,如果它存储在标记为不可修改的内存中,它就会爆炸。您的系统似乎是后者。要解决此问题,您可能需要返回上一行并将其更改为

str2 = malloc(20);

这比您需要的内存要多,但它可以正常工作。

free(str); - 你试图释放常量字符串“hello”,它不是动态分配的内存。这需要在分配 str = "hello"; 之前完成。

free(str2; - 与上述相同的问题。这需要在分配 str2 = "hey jude"; 之前完成。

} - 正确

祝你好运。

【讨论】:

    猜你喜欢
    • 2012-04-25
    • 2020-03-31
    • 2016-02-24
    • 1970-01-01
    • 2014-06-15
    • 1970-01-01
    • 2017-09-17
    • 2020-10-05
    • 2014-10-21
    相关资源
    最近更新 更多