Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这个字符串反转C代码会导致分段错误?_C_String_Segmentation Fault - Fatal编程技术网

为什么这个字符串反转C代码会导致分段错误?

为什么这个字符串反转C代码会导致分段错误?,c,string,segmentation-fault,C,String,Segmentation Fault,我正试图编写代码来反转字符串(我只是想在C编程和指针操作方面做得更好),但我不明白为什么我会得到: #包括 无效反向(字符*s); int main(){ char*s=“teststring”; 反面; 返回0; } 无效反向(字符*s){ int i,j; 焦炭温度; 对于(i=0,j=(strlen(s)-1);i

我正试图编写代码来反转字符串(我只是想在C编程和指针操作方面做得更好),但我不明白为什么我会得到:

#包括
无效反向(字符*s);
int main(){
char*s=“teststring”;
反面;
返回0;
}
无效反向(字符*s){
int i,j;
焦炭温度;
对于(i=0,j=(strlen(s)-1);i
导致分段错误的是第2行和第3行。我知道可能有更好的方法可以做到这一点,但我感兴趣的是找出我的代码中导致分段错误的具体原因


更新:我已按要求包含调用函数。

您的代码可能由于多种原因而出现错误。以下是我想到的

  • s为空
  • s指向保存在只读存储器中的常量字符串
  • s不是以NULL结尾的
  • 我认为#2是最有可能的。你能告诉我们反向通话的地点吗

    编辑

    根据你的样本#2绝对是答案。C/C++中的字符串文字不可修改。正确的类型实际上是
    const char*
    ,而不是
    char*
    。您需要做的是将一个可修改的字符串传递到该缓冲区

    快速示例:

    char* pStr = strdup("foobar");
    reverse(pStr);
    free(pStr);
    

    没有办法仅仅从代码中说出来。最有可能的情况是,您正在传递一个指针,该指针指向无效内存、不可修改内存或其他类型的内存,这些内存无法按照您在此处处理的方式进行处理

    如何调用函数

    添加:您正在传递一个指向字符串文本的指针。字符串文字是不可修改的。不能反转字符串文字

    而是传入指向可修改字符串的指针

    char s[] = "teststring";
    reverse(s); 
    
    这已经在这里解释得透不过气来了<代码>“teststring”
    是字符串文字。字符串文字本身是不可修改的对象。实际上,编译器可能(也将)把它放在只读内存中。当您初始化这样的指针时

    char *s = "teststring";
    
    指针直接指向字符串文字的开头。在一般情况下,任何修改
    s
    所指向内容的尝试都将被视为失败。你可以读,但不能写进去。因此,强烈建议仅使用指向常量变量的指针指向字符串文本

    const char *s = "teststring";
    
    但是当您将
    s
    声明为

    char s[] = "teststring";
    
    您将得到一个完全独立的数组
    s
    ,该数组位于普通可修改内存中,它只是用字符串literal初始化的。这意味着独立的可修改数组
    s
    将从字符串文本中复制其初始值。在此之后,
    s
    数组和字符串文本继续作为完全独立的对象存在。文本仍然是不可修改的,而
    s
    数组是可修改的

    基本上,后一种声明在功能上等同于

    char s[11];
    strcpy(s, "teststring");
    

    你在测试这样的东西吗

    int main() {
        char * str = "foobar";
        reverse(str);
        printf("%s\n", str);
    }
    

    这使str成为字符串文字,您可能无法编辑它(我是segfaults)。如果您定义char*str=strdup(foobar)它应该可以正常工作(对我来说是这样的)。

    您使用的是哪种编译器和调试器?使用gcc和gdb,我将使用-g标志编译代码,然后在gdb中运行它。当它出现故障时,我只需执行一个backtrace(gdb中的bt命令),看看哪一行是导致问题的原因。此外,我将一步一步地运行代码,同时“观察”gdb中的指针值,并知道问题的确切位置

    祝你好运。

    我想s不是空终止的,所以不能工作。因此,for迭代的行为不是您所期望的。 因为strlen的结果将优于s长度,所以您将在不应该在的内存中写入

    此外,s指向由只读内存保存的常量字符串。您不能修改它。尝试使用gets函数初始化s,如示例中所示

    请参见C FAQ列表中的:

    这些初始化之间有什么区别

    char a[] = "string literal";
    char *p  = "string literal";
    
    如果我试图给
    p[I]
    分配一个新值,我的程序就会崩溃

    答复: 字符串文字(C源代码中双引号字符串的正式术语)可以用两种稍有不同的方式使用:

    作为字符数组的初始值设定项,如在
    char a[]
    的声明中,它指定该数组中字符的初始值(如有必要,还指定其大小)

    在其他任何地方,它都会变成一个未命名的静态字符数组,此未命名数组可能存储在只读内存中,因此不必修改。在表达式上下文中,数组像往常一样立即转换为指针(参见第6节),因此第二个声明初始化
    p
    以指向未命名数组的第一个元素

    有些编译器有一个开关控制字符串文字是否可写(用于编译旧代码),有些编译器可能有选项使字符串文字被正式视为
    const char
    的数组(以便更好地捕捉错误)

    (强调矿山)


    另请参见。

    您的声明完全错误:

    char* s = "teststring";
    
    “teststring”存储在代码段中,与代码一样,代码段是只读的。s是指向“teststring”的指针,同时,您试图更改只读内存范围的值。因此,分割错误

    但是:

    char s[] = "teststring";
    

    s用“teststring”初始化,它当然在代码段中,但在本例中,还有一个额外的复制操作正在进行

    正如上面提供的一些答案一样,字符串内存是只读的。但是,有些编译器提供了使用可写字符串进行编译的选项。例如,使用char s[] = "teststring";