为什么这个string反转C代码导致分段错误?

我正在尝试编写代码来反转一个string(我只是想在C编程和指针操作方面做得更好),但我无法弄清楚为什么我得到了一个段错误 :

#include <string.h> void reverse(char *s); int main() { char* s = "teststring"; reverse(s); return 0; } void reverse(char *s) { int i, j; char temp; for (i=0,j = (strlen(s)-1); i < j; i++, j--) { temp = *(s+i); //line 1 *(s+i) = *(s+j); //line 2 *(s+j) = temp; //line 3 } } 

第2行和第3行导致分段错误。 我知道有可能有更好的方法来做到这一点,但我有兴趣找出在我的代码中具体是什么导致了分段错误。

更新 :我已经包含了要求的调用函数。

没有办法只从这个代码说。 最有可能的是,你正在传递一个指向无效内存,不可修改的内存或其他types的内存的指针,这些内存在你处理的时候是无法处理的。

你怎么称呼你的function?

补充:你正在传递一个指向string的指针。 string文字是不可修改的。 您不能反转string文字。

相反,传递一个指向可修改string的指针

 char s[] = "teststring"; reverse(s); 

这已经在这里解释了死亡。 "teststring"是一个string文字。 string文字本身是一个不可修改的对象。 在实践中,编译器可能(也将会)把它放在只读存储器中。 当你初始化一个像这样的指针

 char *s = "teststring"; 

指针直接指向string文本的开头。 在一般情况下,任何修改指向的尝试都被视为失败。 你可以阅读,但你不能写入它。 因此,强烈build议只使用指向constvariables的string文字

 const char *s = "teststring"; 

但是,当你宣布你s

 char s[] = "teststring"; 

你会得到一个完全独立的数组,它位于普通的可修改内存中,它只是用string文字初始化的 。 这意味着独立的可修改数组s将从string文字中获得它的初始值。 之后,你s数组和string继续作为完全独立的对象存在。 文字仍然是不可修改的,而你s数组是可以修改的。

基本上,后者的声明在function上等同于

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

您的代码可能会因多种原因而被暂停。 这些是想到的

  1. s是NULL
  2. s指向一个只读存储器中的conststring
  3. s不是NULL终止

我认为#2是最有可能的。 你能告诉我们反向的呼叫站点吗?

编辑

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

快速示例:

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

你在testing这个东西吗?

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

这使得str是一个string文字,你可能无法编辑它(segfaults对我来说)。 如果你定义了char * str = strdup(foobar)它应该可以正常工作(对我来说)。

你的声明是完全错误的:

 char* s = "teststring"; 

“teststring”存储在只读的代码段中,如代码。 而s是一个指向“teststring”的指针,同时你试图改变一个只读存储器的值。 因此,分段错误。

但是:

 char s[] = "teststring"; 

s被初始化为“teststring”,这当然是在代码段中,但是在这种情况下还有一个额外的复制操作正在进行。

请参阅C FAQ列表中的问题8.5 。

参见Joel的“ Back to Basics” 。

你使用哪个编译器和debugging器? 使用gcc和gdb,我将用-g标志编译代码,然后在gdb中运行它。 当它segfaults,我只是做一个回溯(gdb中的bt命令),看看哪个是导致问题的违规行。 另外,我只是一步一步地运行代码,同时“观察”gdb中的指针值,并知道问题到底在哪里。

祝你好运。

如上面提供的一些答案,string内存是只读的。 但是,有些编译器提供了一个用可写string编译的选项。 例如使用gcc ,3.x版本支持可-fwritable-strings但新版本不支持。

我认为strlen不能工作,因为s不是NULL终止。 所以你的迭代行为不是你所期待的。 由于strlen的结果将超过s的长度,所以你会在记忆中写下你不应该写的东西。

另外s指向一个只读存储器持有的string。 你不能修改它。 尝试通过使用gets函数来初始化s,如在strlen示例中所做的那样