为函数中的指针赋值时的分段错误

时间:2013-10-29 15:53:31

标签: c pointers segmentation-fault undefined-behavior

长时间听众,第一次来电。

如果这个问题已经得到解决,我会道歉(我想这已经被广泛讨论了),但我已经搜索了很多关于指针和其他看似相关主题的问题,但我仍然我无法解决我的问题。

我正在为类项目编写一个 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;
}

4 个答案:

答案 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");
}