C++ const cast, unsure if this is secure

让人想犯罪 __ 提交于 2019-12-23 08:48:26

问题


It maybe seems to be a silly question but i really need to clarify this:

Will this bring any danger to my program?

Is the const_cast even needed?

If i change the input pointers values in place will it work safely with std::string or will it create undefined behaviour?

So far the only concern is that this could affect the string "some_text" whenever I modify the input pointer and makes it unusable.

std::string some_text = "Text with some input";

char * input = const_cast<char*>(some_text.c_str());

Thanks for giving me some hints, i would like to avoid the shoot in my own foot


回答1:


As an example of evil behavior: the interaction with gcc's Copy On Write implementation.

#include <string>
#include <iostream>

int main() {
    std::string const original = "Hello, World!";
    std::string copy = original;

    char* c = const_cast<char*>(copy.c_str());
    c[0] = 'J';

    std::cout << original << "\n";
}

In action at ideone.

Jello, World!

The issue ? As the name implies, gcc's implementation of std::string uses a ref-counted shared buffer under the cover. When a string is modified, the implementation will neatly check if the buffer is shared at the moment, and if it is, copy it before modifying it, ensuring that other strings sharing this buffer are not affected by the new write (thus the name, copy on write).

Now, with your evil program, you access the shared buffer via a const-method (promising not to modify anything), but you do modify it!

Note that with MSVC's implementation, which does not use Copy On Write, the behavior would be different ("Hello, World!" would be correctly printed).

This is exactly the essence of Undefined Behavior.




回答2:


To modify an inherently const object by casting away its constness using const_cast is an Undefined Behavior.

string::c_str() returns a const char *, i.e: a pointer to a constant c-style string. Technically, modifying this will result in Undefined Behavior.

Note, that the use of const_cast is when you have a const pointer to a non const data and you wish to modify the non-constant data.




回答3:


Simply casting will not bring forth an undefined behavior. Modifying the data pointed at, however, will. (Also see ISO 14882:98 5.2.7-7).

If you want a pointer to modifiable data, you can have a

std::vector<char> wtf(str.begin(), str.end());
char* lol= &wtf[0];



回答4:


The std::string manages it's own memory internally, which is why it returns a pointer to that memory directly as it does with the c_str() function. It makes sure it's constant so that your compiler will warn you if you try to do modifiy it.

Using const_cast in that way literally casts away such safety and is only an arguably acceptable practice if you are absolutely sure that memory will not be modified.

If you can't guarantee this then you must copy the string and use the copy.; it's certainly a lot safer to do this in any event (you can use strcpy).




回答5:


See the C++ reference website:

const char* c_str ( ) const;

"Generates a null-terminated sequence of characters (c-string) with the same content as the string object and returns it as a pointer to an array of characters.

A terminating null character is automatically appended.

The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only guaranteed to remain unchanged until the next call to a non-constant member function of the string object."




回答6:


Yes, it will bring danger, because

  1. input points to whatever c_str happens to be right now, but if some_text ever changes or goes away, you'll be left with a pointer that points to garbage. The value of c_str is guaranteed to be valid only as long as the string doesn't change. And even, formally, only if you don't call c_str() on other strings too.
  2. Why do you need to cast away the const? You're not planning on writing to *input, are you? That is a no-no!



回答7:


This is a very bad thing to do. Check out what std::string::c_str() does and agree with me.

Second, consider why you want a non-const access to the internals of the std::string. Apparently you want to modify the contents, because otherwise you would use a const char pointer. Also you are concerned that you don't want to change the original string. Why not write

std::string input( some_text );

Then you have a std::string that you can mess with without affecting the original, and you have std::string functionality instead of having to work with a raw C++ pointer...




回答8:


Another spin on this is that it makes code extremely difficult to maintain. Case in point: a few years ago I had to refactor some code containing long functions. The author had written the function signatures to accept const parameters but then was const_casting them within the function to remove the constness. This broke the implied guarantee given by the function and made it very difficult to know whether the parameter has changed or not within the rest of the body of the code.

In short, if you have control over the string and you think you'll need to change it, make it non-const in the first place. If you don't then you'll have to take a copy and work with that.




回答9:


it is UB. For example, you can do something like this this:

size_t const size = (sizeof(int) == 4 ? 1024 : 2048);
int arr[size];

without any cast and the comiler will not report an error. But this code is illegal. The morale is that you need consider action each time.



来源:https://stackoverflow.com/questions/10293805/c-const-cast-unsure-if-this-is-secure

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!