我正在尝试编写代码来反转字符串(我只是想在C编程和指针操作方面做得更好),但我无法弄清楚为什么我得到segmentation fault:
#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行。我知道可能有更好的方法可以做到这一点,但我有兴趣找出我的代码中的导致分段错误。
更新:我已按要求包含了调用功能。
答案 0 :(得分:50)
没有办法仅仅通过该代码说出来。最有可能的是,你传入一个指针指向无效内存,不可修改的内存或其他类型的内存,这些内存无法按照您在此处理的方式进行处理。
你如何称呼你的职能?
添加:您正在传递指向字符串文字的指针。字符串文字是不可修改的。你无法反转字符串文字。
传入指向可修改字符串的指针
char s[] = "teststring";
reverse(s);
这已经在这里被解释为死亡。 "teststring"
是一个字符串文字。字符串文字本身是一个不可修改的对象。实际上,编译器可能(并将把它)放在只读存储器中。初始化类似
char *s = "teststring";
指针直接指向字符串文字的开头。在一般情况下,任何修改s
指向的内容的尝试都被视为失败。你可以阅读它,但你不能写入它。因此,强烈建议仅指向带有指针到const变量的字符串文字
const char *s = "teststring";
但是当你宣布s
为
char s[] = "teststring";
你得到一个完全独立的数组s
,它位于普通的可修改内存中,只是初始化,带有字符串文字。这意味着独立的可修改数组s
将从字符串文字中获取其初始值复制。之后,您的s
数组和字符串文字继续作为完全独立的对象存在。文字仍然是不可修改的,而您的s
数组是可修改的。
基本上,后一种声明在功能上等同于
char s[11];
strcpy(s, "teststring");
答案 1 :(得分:9)
由于多种原因,您的代码可能是segfaulting。以下是我想到的那些
我认为#2最有可能。你能告诉我们反向呼叫站点吗?
编辑
基于您的样本#2绝对是答案。 C / C ++中的字符串文字不可修改。正确的类型实际上是const char*
而不是char*
。您需要做的是将可修改的字符串传递到该缓冲区。
快速举例:
char* pStr = strdup("foobar");
reverse(pStr);
free(pStr);
答案 2 :(得分:2)
你在测试这样的东西吗?
int main() {
char * str = "foobar";
reverse(str);
printf("%s\n", str);
}
这使str成为字符串文字,你可能无法编辑它(对我来说是段错误)。如果您定义char * str = strdup(foobar)
它应该可以正常工作(对我而言)。
答案 3 :(得分:2)
你的声明是完全错误的:
char* s = "teststring";
“teststring”存储在代码段中,它是只读的,就像代码一样。并且,s是指向“teststring”的指针,同时,您正在尝试更改只读内存范围的值。因此,分割错误。
但是:
char s[] = "teststring";
用“teststring”初始化,当然这是在代码段中,但在这种情况下,还有一个额外的复制操作正在进行。
答案 4 :(得分:0)
您使用的是哪种编译器和调试器?使用gcc和gdb,我将使用-g标志编译代码,然后在gdb中运行它。当它出现段错误时,我只会做一个回溯(gdb中的bt命令)并查看哪个是导致问题的违规行。另外,我只是一步一步地运行代码,同时“观察”gdb中的指针值并知道问题究竟在哪里。
祝你好运。答案 5 :(得分:0)
请参阅C FAQ列表中的Question 1.32:
这些初始化之间有什么区别?
char a[] = "string literal"; char *p = "string literal";
如果我尝试为
p[i]
分配新值,我的程序会崩溃。答案:
字符串文字(C源中双引号字符串的正式术语)可以两种略有不同的方式使用:
作为char数组的初始值设定项,如
char a[]
的声明中所述,它指定该数组中字符的初始值(如果需要,还指定其大小)。在其他任何地方,它变成一个未命名的静态字符数组,而 这个未命名的数组可能存储在只读内存中,因此无法修改 。在表达式上下文中,像往常一样将数组一次转换为指针(参见第6节),因此第二个声明初始化
p
以指向未命名数组的第一个元素。有些编译器有一个开关控制字符串文字是否可写(用于编译旧代码),有些编译器可能有选项可以将字符串文字正式视为
const char
的数组(为了更好地捕获错误)(强调我的)
请参阅Back to Basics Joel。
答案 6 :(得分:0)
正如上面提供的一些答案,字符串存储器是只读的。但是,一些编译器提供了使用可写字符串进行编译的选项。例如。使用gcc
,支持3.x版-fwritable-strings
但新版本不支持。
答案 7 :(得分:-1)