长时间听众,第一次来电。
如果这个问题已经得到解决,我会道歉(我想这已经被广泛讨论了),但我已经搜索了很多关于指针和其他看似相关主题的问题,但我仍然我无法解决我的问题。
我正在为类项目编写一个 string 库,当我尝试这个时遇到分段错误错误:
#include "str2107.h"
#include <stdio.h>
void lstrip(char *s) {
char *p, *q;
p = q = s;
while (*p == ' ' && *p != '\0') {
*p++;
}
while (*p != '\0') {
*q = *p; //this is where the actual segmentation fault occurs.
p++;
q++;
}
*q = '\0';
}
我的主程序如下:
#include <stdio.h>
#include <stdlib.h>
#include "str2107.h"
int main(int argc, char** argv) {
char *z1 = " weeee";
printf("lstrip function\n");
printf("%s\n",z1);
lstrip(z1);
printf("%s\n",z1);
return 0;
}
答案 0 :(得分:6)
z1
指向字符串文字,修改字符串文字为undefined behavior。或者,您可以使用以下z1
声明,该声明可以修改:
char z1[] = " weeee";
如果我们查看C99草案标准部分6.4.5
字符串文字段 6 说(强调我的):
如果这些数组的元素具有不同的数据,则未指定 适当的价值观如果程序试图修改这样的数组,则行为是 未定义。强>
其他一些观点,如WhozCraig指出这一行:
while (*p == ' ' && *p != '\0') {
可以更简洁地写成:
while (*p == ' ' ) {
你也在这里使用间接:
*p++;
但您实际上并未使用结果值,因此您可以将其更改为:
p++;
答案 1 :(得分:1)
当您编写char *z1 = " weeee";
时,z1
是指针,指向代码部分中的内存,因此您可以'改变它。
如果您更改char z1[] = " weeee";
,则z1
是堆栈上的 阵列,您可以更改它。
如果您已经写过char const *z1 = "...";
,那么它将是编译错误,这比分段错误更好,更可取。
答案 2 :(得分:0)
char *z1 = " weeee";
应该是
const char *z1 = " weeee";
因为字符串文字是常量。尝试类似:
const char *z1 = " weeee";
char *z2 = strdup(z1);
lstrip(z2);
要在可变字符串上调用lstrip
,同时仍然z2
char*
char[]
(如果它是{{1}}不是您想要的那样)。
答案 3 :(得分:0)
正如许多其他人已经向你指出的那样,当你写道:
char *whatever = "some value";
这与以下内容大不相同:
char *whatever = malloc(length("some value") + 1); strcpy(whatever, "some value");
区别在于文字(即在编译时定义的字符串)可以是常量,但我不知道它是总是还是必需保持不变。由于不应修改常量,并且在字符串中放置'\ 0'字符,这会导致分段错误。
这可能有很多原因,但我所知道的简单方法是,如果程序知道每次使用同一个字符串都可以安全重用,那么该程序可以进行优化。
举个例子:
char *whatever1 = malloc(length("some value") + 1); strcpy(whatever1, "some value"); char *whatever2 = malloc(length("some value") + 1); strcpy(whatever2, "some value"); if(whatever1 == whatever2) { printf("This should never happen!\n"); } if("some value" == "some value") { printf("A good compiler should always do this!\n"); }