-1

Here is a problem. When I try to convert it by using strncpy_s, array has some type of "trash data" from memory in the end of it. Even when I fill buffer with "\0". How to convert it clear?

typedef class Ryadok {
private:
    int LengthOf = 0;
    char text[20];
    string* address;
public:
    Ryadok(string strin) {
        this->text[0] = '\0';
        memset(text, '\0', sizeof(text));
        strncpy_s(text, strin.c_str(), sizeof(text) - 1);
        this->address = &strin;
        for (int i = 0; i < sizeof(strin); i++) {
            cout << this->text[i];
        }
    }
    ~Ryadok() {
    }
}*cPtr;
int main()
{
    Ryadok example("sdsdfsdf");
}
  • 1
    One question -- why is it necessary to copy to a char array? Why not keep everything as `std::string`? Second, `this->address = &strin;` -- this will not work, since `strin` is a temporary variable. And why the `typedef class`? Why not simply `class`? – PaulMcKenzie Apr 15 '20 at 13:58
  • because in my task I need to make char pointer on strin. Because I will need it in future, I'm talking about typedef. This is a little piece of code – smthwrng Apr 15 '20 at 14:02
  • 1
    Your task will not work -- what do you think will happen after that function returns? What will happen to that temporary variable `strin`? It goes away -- so what will the address you stored point to? – PaulMcKenzie Apr 15 '20 at 14:04
  • Understood. I just don't know how to give char array into class constructor, that's why I need to try some types of sodomy like that – smthwrng Apr 15 '20 at 14:06
  • I don't even quite understand what you're trying to do. Why the complexity over simply doing a `strncpy` to the char array (if that's what you're trying to do). What is the deal with `string* address;`? What's that all for? – PaulMcKenzie Apr 15 '20 at 14:08
  • Why is `string* address` a `pointer`? Not only that, you're pointing `string* address` to a local `variable` which will go out of scope in the `constructor` – WBuck Apr 15 '20 at 14:08
  • This smells like an [XY problem](https://en.wikipedia.org/wiki/XY_problem). You will probably _never_ need to do what you're trying to do. Present the actual problem you're trying to solve and someone may come up with a better way. – Ted Lyngmo Apr 15 '20 at 14:08
  • 1
    Looks more like a [Rube Goldberg](https://en.wikipedia.org/wiki/Rube_Goldberg_machine) attempt of solving a problem. – PaulMcKenzie Apr 15 '20 at 14:10
  • 1
    `sizeof(strin)` does not do what you think it does. – aschepler Apr 15 '20 at 14:10
  • 1
    Just store the value `string strin` in to `string address` (note `address` is no longer a `pointer`). Then, via `address` you'll have access to the underlying `const char*` or `char*` by using `address.c_str( )` and `address.data()` respectively – WBuck Apr 15 '20 at 14:13

2 Answers2

0

When using the strncpy_s function you tell it to copy as many chars as will fit into your buffer "text". Since the string you create the "example" instance with is shorter, the copy function will keep going after the end of the actual string.

That is where your garbage comes from. Even worse you risk a Segmentation Fault this way. Your code might access parts of the RAM it is not allowed to read from. That will cause it to crash.

You are right though to copy the data pointed to by the return of c_str(). The pointer returned by c_str() points to data that belongs to the std::string object and might be changed or even invalidated by that object. (Read more here)

Here's a modified version of your code that should avoid the garbage:

typedef class Ryadok {
    private:
        int LengthOf = 0;
        char text[20];
        string* address;
    public:
        Ryadok(string strin) {
            this->text[0] = '\0';
            memset(text, '\0', sizeof(text));

            if(strin.length()+1 <= sizeof(text)) {
                strncpy_s(text, strin.c_str(), strin.length()+1);
            } else {
                //some error handling needed since our buffer is too small
            }

            this->address = &strin;
            for (int i = 0; i < sizeof(strin); i++) {
                cout << this->text[i];
            }
        }
    ~Ryadok() {
    }
}*cPtr;

int main()
{
    Ryadok example("sdsdfsdf");
}
Henning
  • 1
  • 2
0

The idea to use c_str() function to convert the std::string to a a-string. Then we can simply call strcpy() function to copu the c-string into char array

std::string s = "Hello World!";
char cstr[s.size() + 1];
strcpy(cstr, s.c_str());    // or pass &s[0]
std::cout << cstr << '\n';
return 0;
  • `char cstr[s.size() + 1];` -- Unfortunately, this is not valid C++. – PaulMcKenzie Apr 16 '20 at 04:22
  • Use the header file `#include ` . It will definitely work – Mohammed Shameem Apr 17 '20 at 13:48
  • No, it will not work. You are declaring an array with a runtime value to denote the size. It is not valid C++. You are another victim of the default `g++` or `clang` compiler mode, where you are fooled into thinking that variable-length-arrays exist in C++. – PaulMcKenzie Apr 17 '20 at 13:48