为什么这个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");
您的代码可能会因多种原因而被暂停。 这些是想到的
- s是NULL
- s指向一个只读存储器中的conststring
- 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示例中所做的那样