c - strcpy 的段错误,即使指针有指针

标签 c segmentation-fault

void trim(char *line)
{
    int i = 0;
    char new_line[strlen(line)];
    char *start_line = line;
    while (*line != '\0')
    {
        if (*line != ' ' && *line != '\t')
        {
            new_line[i] = *line;
            i++;
        }
        line++;
    }
    new_line[i] = '\0';
    printf("%s\n", start_line);
    printf("%s\n", new_line);
    strcpy(start_line, new_line);
}

我真的找不到这里的问题。我的指针已初始化,我制作了一个指针以开始字符串行。最后我想在旧行中复制新行,这样调用者的行值就会改变。

但是 strcpy() 会产生段错误。怎么了?

这是调用 trim() 的代码:

char *str = "Irish People Try American Food";
printf("%s\n", str);
trim(str);
printf("%s\n", str);

最佳答案

你需要展示整个程序;什么叫做“修剪()”? Paul R 的回答是正确的,你少了一个字符,至少应该是:

char new_line[strlen(line) + 1];

但是,这并不总是会导致段错误,如果发生了,它可能不会在 strcpy() 处。

strcpy(start_line, new_line) 出错的可能原因是 start_line 指向 line 的原始值。很可能您正在调用该函数:

int main() {
    trim("blah blah\tblah");
    return 0;
}

如果是这样,line 是指向无法修改的常量 字符数组的指针。在许多操作系统上,它存储在只读内存区域中,因此如果进行写入尝试,它将立即导致段错误。因此 strcpy() 在尝试写入此只读位置时会出错。

作为快速测试试试这个:

int main() {
    char test[100] = "blah blah\tblah";
    trim(test);
    return 0;
}

如果它有效,那就是你的 strcpy() 错误的具体问题。

编辑 - 后来更新了问题以包含 main() 调用函数,该函数确认 trim 函数是使用指向字符串常量的指针调用的。问题行是:

char *str = "Irish People Try American Food";

这将创建一个字符串文字,一个包含 31 个字符的数组,其中包括一个无法修改的空终止符。然后使用此常量 数组的地址初始化指针 str

更正的方法是分配一个规则的字符数组,然后用已知的字符串初始化它。在这种情况下,分配和临时常量字符串文字可能会也可能不会被优化掉,但最终结果总是相同的——一个用所需文本初始化的可写字符数组:

char str[100] = "Irish People Try American Food";
/* or */
char str2[] = "American People Like Irish Beer";
/* or */
char *str3[37];
strcpy(str3, "And German Beer"); /* example only, need to check length */

这些创建长度分别为 100、32 和 37 的普通可写字符数组。然后使用给定的字符串对每个进行初始化。

ANSI/ISO C 标准定义了这样一种语言,即字符串文字是一个char 不能修改 的数组。即使它最初是在 C89 中标准化的,情况也是如此。在此之前,字符串文字通常是可写的,例如在非常早期的 UNIX 代码的准标准 K&R C 中。

Identical string literals of either form need not be distinct. If the program attempts to modify a string literal of either form, the behavior is undefined. - ANSI X3.159-1989

从那时起,许多 C89 和更新的编译器将此数组放入 .text 或 .rodata 段中,在这些段中它甚至可能在物理上不可写(ROM、只读 MMU 页面等),如此处发现。编译器也可能将重复的字符串常量合并为一个以节省空间——您也不会写入其中的“一个”!

事实上,这些语义上不可写的字符串仍然保留为 char * 类型,并且可以这样分配和传递它们,这被认为是一种妥协,即使 C89 标准正在制定中起草的。他们没有使用当时全新的类型限定符 const 被描述为“不完全满意的结果”。参见 Richie's (DMR's)解释。

很显然,近 30 年后,这个结果仍然回旋镖,让人们大吃一惊。

关于c - strcpy 的段错误,即使指针有指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35872024/

相关文章:

c - Diab 编译器中的解析错误

C编程问题无关变量在使用STRCPY后被覆盖

c - 预期声明说明符或 '...' 之前的 'compareWeight'

python - C 与 C 中 Python 扩展的速度

C编程按位: value of -1 >> 1

c++ - 使用 g++7 构建的代码因访问未对齐的内存而崩溃

c - 总线错误和段错误取决于输入的值

c - 带指针的双向链表段错误

c - 程序结束后返回值 3221225477

c - 如何在c中将文本文件拆分为多个部分