C:代码生成一个指向字符串的段错误非花费点?

问题描述 投票:0回答:2

我正在尝试调用以下代码,这会导致段错误。我了解这表明程序正在尝试访问它无权访问的内存。我看到*b = *c行引起了问题,但是据我了解,这应该是有效的操作。#include

int main(int argc, char *argv[])
{
    char *b = "defg";
    char *c = "hijk";

    printf("%c,%c", *b, *c);
    fflush(stdout);

    *b = *c;

    return 0;
}

$ gcc -g -Wall test108b.c && ./a.out
$ ./a.out
d,hMemory fault(coredump)

更新:使用x[]定义字符数组与使用指向字符串文字的指针有效!以下备用代码有效:

#include <stdio.h>

int main(int argc, char *argv[])
{
    char b[] = "defg";
    char c[] = "hijk";

    char *bp = b;
    char *cp = c;
    while (*bp)
     *bp++ = *cp++;

    bp = b;
    while (*bp)
     printf("%c", *bp++);

    return 0;
}


gcc -g -Wall test108b.c && ./a.out
hijk

有人知道为什么第二版代码有效而第一版无效吗?

c
2个回答
1
投票

您的第一行是一个错误:

char *b = "defg";

字符串文字是只读的,应该分配给const char*指针以反映这一点。

如果要使用字符串初始化char array(不是指针),则可以执行此操作,并且可以对其进行修改:

char b[] = "defg";

请注意,这是一个例外,仅适用于使用字符串文字进行初始化。这行不通:

char c[] = b;

0
投票

String文字是只读的,除了字符数组的初始化外,但实际上情况要复杂一些。此行为取决于您的编译器和体系结构,但是对于gcc和x86,这似乎是该行为。我相信这是出于安全原因。过去曾经有一个标记来启用您想要的行为,但是该标记也已从gcc中删除。最好的选择是将数组初始化为char数组。

#include <stdio.h>

int main(int argc, char *argv[])
{
    char b[] = "defg";
    char c[] = "hijk";

    printf("%c,%c", *b, *c);
    fflush(stdout);
    *b = *c;
    char *bp = b;
#if 0
    while (*b)
     *b++ = *c++;

    while (*bp)
     printf("%c", *bp++);
#endif
    return 0;
}

[另外,我怀疑这只是一个演示程序,用于显示您所询问的行为,但是复制字符串的最佳方法是使用libbsd库中的strlcpy之类的东西(如果您使用的是Linux)。它的null终止与安全性较低的同级strcpy和strncpy不同。

以下是一些有用的编译器标志:

如果出现此错误,此标志将警告您。

-Wwrite-strings

此标志将警告您比较字符串文字的内存地址。

-地址

希望有所帮助

© www.soinside.com 2019 - 2024. All rights reserved.