简体   繁体   English

Visual Studio C ++编译器中的错误?

[英]Bug in Visual Studio C++ compiler?

This code behaves weird in MS Visual Studio: 此代码在MS Visual Studio中表现得很奇怪:

char *s = "hello";
s[0] = 'a';
printf(s); 

In release build with optimization turned on it ignores s[0] = 'a' and prints "hello". 在启用优化的发布版本中,它忽略s [0] ='a'并打印“hello”。 Without optimization or in debug build it crashes with access violation. 如果没有优化或在调试版本中,它会因访问冲突而崩溃。
Is this behavior is c++ standard compliant or no? 这种行为是符合c ++标准还是没有? In my opinion, compiler should only allow constant references to string literals, ie 在我看来,编译器应该只允许对字符串文字的常量引用,即

const char *s = "hello";

EDIT : I know why it works like this, I do not understand why I am allowed to make non const reference to read only memory. 编辑 :我知道为什么它这样工作,我不明白为什么我被允许非const引用只读内存。

No, it's not a bug in the compiler. 不,这不是编译器中的错误。 When you write: 当你写:

char* s = "hello";

The string constant "hello" will be placed in a read-only section and should generate an exception if you try to modify it. 字符串常量"hello"将放在只读部分中,如果您尝试修改它,则应生成异常。 (an OS exception, not a C++ exception). (OS异常,而不是C ++异常)。

To make it writable, you have to either use an array: 要使其可写,您必须使用数组:

char s[] = { 'h', 'e', 'l', 'l', 'o', 0 };

or, if you really need a pointer, make it point to an array: 或者,如果你真的需要一个指针,让它指向一个数组:

char _s[] = { 'h', 'e', 'l', 'l', 'o', 0 };
char* s = _s;

I can see your point about only allowing const pointers to be initialized with string literals, but I think that would break a lot of existing code. 我可以看到你的观点,即只允许使用字符串文字初始化const指针,但我认为这会破坏很多现有代码。

The reason why this code is allowed in the first place (rather than requiring the declaration to be of type char const* ) is backwards compatibility to old C code. 首先允许此代码的原因(而不是要求声明为char const*类型)是对旧C代码的向后兼容性。

Most modern compilers in strict mode will issue a warning for the above code, though! 但是,严格模式下的大多数现代编译器都会对上面的代码发出警告

我认为允许C ++编译器按照标准在只读存储器页面中分配字符串文字。

This won't work because *s is pointing to the memory address of a string constant, which you're not allowed to change. 这不起作用,因为* s指向字符串常量的内存地址,您不允许更改。

I'm actually a little surprised you don't don't get an access violation when it's compiled with optimizations. 我实际上有点惊讶你在使用优化编译时不会遇到访问冲突。

char *s = "foo";

is a tricky pony. 是一个棘手的小马。 It doesn't tell you that this really is a read-only string when in reality it is. 它并没有告诉你这实际上是一个只读字符串。 This is so, because, you could have your colleague write another string like: 就是这样,因为,你可以让你的同事写下另一个字符串,如:

char *t = "foo";

Now, the compiler, at its helpful best will keep only one copy, and changing one would mean a lot of work only to keep you and your friend happy. 现在,编译器在其最有用的情况下只保留一个副本,而更改一个副本意味着很多工作只会让你和你的朋友感到高兴。 So, it doesn't try to do that. 所以,它并没有尝试这样做。 This is something you should find in the standard. 这是你应该在标准中找到的东西。 Guess what, what you're doing invokes UB. 猜猜你正在做什么调用UB。

That said, if you were to have your way, it would break a lot of legacy code which the poor guys at the Standards Committee couldn't afford. 也就是说,如果你按照自己的方式行事,它将打破标准委员会中的穷人无法负担的许多遗留代码。 So, there you are. 那么,你就是。

Remember the const we are guilty of carefree usage wasn't born in a day. 记住const我们犯了无忧无虑的用法并非一天出生。 Bjarne did a lot of soul-searching and so did a lot of others whether to put it in or not. Bjarne做了很多自我反省,很多其他人也做了很多的反省。 In fact, he had this excellent idea of having read-only and write-only variables ... but I'll save that story for another day. 事实上,他有一个关于只读和只写变量的优秀想法......但是我会把这个故事保存到另一天。

And finally, there is our good friend C, who we need to take care of. 最后,还有我们的好朋友C,我们需要照顾他们。 So ... 所以......

As the others said, you can't modify a string literal. 正如其他人所说,你无法修改字符串文字。 I also wonder why you don't get a compiler warning in your code. 我也想知道为什么你的代码中没有编译器警告。 The compiler can for sure figure out that you're trying to write to read only memory. 编译器可以肯定地发现你正在尝试写入只读内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM