【问题标题】:ANSI C strstr() not working with pointers [duplicate]ANSI C strstr()不适用于指针[重复]
【发布时间】:2016-11-06 10:04:00
【问题描述】:

我正在尝试使用 strstr() 在字符串中查找子字符串。仅使用 char[] 有效,char* 无效,导致分段错误。

所以这个是有效的:

int main() {
    char str[] = "apple apple peach";
    char *p;

    p = strstr(str, "peach");
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    return 0;
}

但是这个不行:

int main() {
    char *str = "apple apple peach";
    char *p;

    p = strstr(str, "peach");
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    return 0;
}

这两个都不是:

int main() {
    char *str = "apple apple peach";
    char *peach = "peach";
    char *p;

    p = strstr(str, peach);
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    return 0;
}

这两个都不是:

int main() {
    char *str = "apple apple peach";
    char peach[] = "peach";
    char *p;

    p = strstr(str, peach);
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    return 0;
}

这是一个已知的错误或功能吗?

【问题讨论】:

  • 这不是strstr的问题。您不能写入字符串常量。它被放入内存的只读部分。
  • 致 OP:使用 -Wwrite-strings 编译以获取有关此问题的警告。
  • 或使用 -Wall 和 -Wextra 更好,当您使用 gcc 或为您的编译器使用等效标志时。并检查每个警告。
  • @12431234123412341234123。请注意,-Wall -Wextranot 启用了 write-strings。以前是,但现在不是了。

标签: c strstr strncpy string.h


【解决方案1】:

你的问题不是strstr,而是strncpy。在指针的情况下,您使用strncpy 尝试写入字符串字面量,它是常量。

【讨论】:

  • 感谢您的回答
【解决方案2】:

string-literal 修改是不安全的! char[] 的那个成功只是因为strncpy(p, "apple", 5); 修改了 string-literal 的复制版本不是字符串文字本身。标准中的相关段落如下:

6.4.5,第 6 段

... 然后使用多字节字符序列初始化一个静态存储持续时间和长度刚好足以包含该序列的数组...

6.4.5,第 7 段

...如果程序尝试修改这样的数组,则行为未定义。

简而言之,string-literal 被(概念上) 替换为数组,修改它是不安全的。请注意,string-literal 不一定是 const 限定的,尽管 MSVC++ 似乎要求 string-literalconst char * 或 const 限定的。

【讨论】:

    【解决方案3】:

    它与strstr 无关:它按预期工作。当您尝试修改分配给字符串文字的内存时,崩溃发生在strcpy。这是未定义的行为。

    解决这个问题的关键是将数据放入允许写入的内存中。您的第一个程序通过声明 str 一个数组来实现:

    char str[] = "apple apple peach";
    

    那不是UB,所以程序运行完成。另一种选择是在动态内存中分配str,如下所示:

    char *str = malloc(20);
    strcpy(str, "apple apple peach");
    char *p;
    p = strstr(str, "peach");
    if (p!= NULL) {
        strncpy(p, "apple", 5);
    }
    free(str);
    

    【讨论】:

    • 太好了,谢谢。那是被遗忘的一点。 :)
    猜你喜欢
    • 2023-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    相关资源
    最近更新 更多