明显的segmentation fault没有编译器警告

7

我对这个没有任何警告就编译通过感到惊讶:

int main()
{ 
    *"abc" = '\0';
}

使用 gcc main.c -Wall -Wextraclang main.c -Weverything 命令时,为什么没有任何警告?这段代码有可能不会导致分段错误吗?

4
更好的问题是:为什么"abc"[0] = '\0';会有警告?这似乎是gcc中的一些不一致。 - Lundin
1
为什么要这样做?char *没有被const限定。如果你找到了一种语言的编译器,可以在代码错误时生成诊断信息,请申请解决停机问题的诺贝尔奖。并且,请提供标准的参考,解释为什么必须有分段错误或任何其他特定的行为。 - too honest for this site
2
@Olaf也许我可以反过来问,正如Lundin所说:如果char *没有被const限定,为什么使用"abc"[0] = '\0';会出现警告assignment of read-only location - Bilow
2
你可能会为许多这样的例子想出gcc“不警告”的情况。问题是是否需要这样做。答案是不需要。因为你的代码调用了未定义行为。虽然如果gcc识别这些事情(无论是否未定义)会很好,但它不能在所有这种情况下通用地执行此操作。 - P.P
1
作为@Lundin评论的附言:*(“ABC”+ 0)= '\0';也不会发出警告。那将是索引运算符的确切等效物。 - too honest for this site
显示剩余6条评论
1个回答

4
您可以使用-Wwrite-strings在GCC中获取此代码的警告。从GCC文档中了解到:

-Wwrite-strings

编译C语言时,将字符串常量的类型设置为const char[length],这样将其地址复制到非const char *指针中会得到一个警告。如果您在声明和原型中非常小心地使用const,则这些警告将帮助您在编译时找到可能尝试写入字符串常量的代码。否则,它只是一种麻烦。这就是为什么我们没有让-Wall请求这些警告。

编译C ++时,警告已停用从字符串字面值到char *的转换。对于C ++程序,默认情况下启用此警告。

"是否有任何方法不引发段错误?" -> 修改字符串文字是未定义行为。因此,任何事情都可能发生,包括不会导致段错误。


这并没有回答为什么它会警告等价的索引运算符。 - too honest for this site
哈哈,人们会认为-Wall会覆盖所有警告。如果不行,-Wextra就会覆盖其余部分。这是多么误导人啊。 - savram
你有相关链接吗?我在想即使我不能依赖它会发生段错误,它也不会发生段错误的原因是什么?还有其他可能发生的情况吗? - Bilow
1
@SamuelPeter:如果我们谈论像x86这样的完整操作系统系统:不,它不是链接器,而是操作系统加载程序将rodata部分放置到写保护RAM中。如果我们谈论共享库,即动态链接/加载,事情会变得更加复杂。但我只会把它留在UB上;那就是所有人需要关心的。把段错误和链接器引入游戏中确实令人困惑。除非真正必要,否则永远不要改变抽象级别。另一方面,UB是编程和C特别是基本概念。提问者应该理解这些基础知识或进行研究。 - too honest for this site
1
@Olaf,正是因为像你这样的人只讲未定义行为而不解释更多内容,所以我还没有理解。我会为此提出新问题。 - Bilow
显示剩余16条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接