There is a class (structure) external and internal (inside the first). Made to overload the operator [][] . In the task, it was necessary to cut the string "from" and "to" by this operator.

I in Maine display a lot of information. INFA displayed correctly and without oddities. BUT. If I declare std::cout << nTemp in the substring structure, then the output immediately changes. All the lines that I wrote in Maine disappear, and in general, it seems to me that the program is starting to behave very suspiciously.

 struct String { struct Substring{ //ВТОРАЯ часть //-------------- const String operator [](int index) const{ //Здесь проводим аналогичные операции, как и со String и возвращаем уже конечный String int nTemp = index - nPastIndex; char SecStr[nTemp+1]; SecStr[nTemp]='\0'; //std::cout<<nTemp; // Тут проблемный участок strncpy(SecStr, str, nTemp); String pStr(SecStr); return pStr; } size_t nPastIndex; size_t size; char *str; char *secstr; }; //ПЕРВАЯ часть //-------------- const Substring operator [](const int index)const{ //Определяем будущий размер массива и определяем его int nTemp = size - index; char SecStr[nTemp]; SecStr[nTemp]='\0'; //Копируем строку через string в наш массив и передаем этот массив конструктору, // который добавляет его в свои поля. Возвращаем объект в следующую кв. скобку [] // - то есть в Substring (он выше) std::string const szNewStr(str); strcpy(SecStr, szNewStr.substr(index, size).c_str() ); Substring NewStr(SecStr,index); return NewStr; } size_t size; char *str; char *secstr; }; //main для тестов //----------------- int main(){ const String s("hello world."); String const hello("hello world."); std::cout<<hello.str<<" "<<strlen(hello.str)<<std::endl; String const hell = hello[0][4]; std::cout<<hell.str<<" "<<strlen(hell.str)<<std::endl; String const ell = hello[1][4]; std::cout<<ell.str<<" "<<strlen(ell.str)<<std::endl; String const ll = hello[0][0]; std::cout<<ll.str<<" "<<strlen(ll.str)<<std::endl; String const l = hello[3][9]; std::cout<<l.str<<" "<<strlen(l.str)<<std::endl; if(strcmp(s[1][4].str, "ell")==0){ std::cout<<"True"<<std::endl; } return 0; } 
  • In general, there is a class (structure) external and internal (inside the first). Made to overload the operator [] []. In the task, it was necessary to cut the string "from" and "to" by this operator. What is my question: I am mapping a lot of information. INFA displayed correctly and without oddities. BUT. If I declare "std :: cout nTemp" in the method of the structure String (signed as "problem area"), then all the lines from Maine cease to be output and in general the program starts to behave very strange. - Ligvest O
  • If there are no ideas, then I would be glad to at least some direction, why this can be so when working with streaming IO. - Ligvest O
  • You have a String structure that does not contain a destructor and a copy constructor - do you know that you have a memory leak? - VladD
  • What does the Substring constructor look like? It is important. - VladD
  • It is better to give an example completely. That it could be compiled and tested. - KoVadim

2 answers 2

Let's start with :)

 String::String(const char *str) { size = strlen(str); this->str = new char[size]; strcpy(this->str, str); } 

here a buffer is created in length equal to the string itself. Since the length is clearly not preserved, the size of the buffer will be unknown to us. All other functions that will work with this buffer will not be able to determine its size. Functions like strcpy hope that at the very end there is a null character.

And when you later call the code in line 93

 if(strcmp(s[1][4].str, "ell")==0){ std::cout<<"True"<<std::endl; } 

then strcmp goes into the dressing. It will scan your string and outside it until it finds a zero. And it can be long and tedious.

Take another function

 Substring(const char *str = "", size_t nPastIndex = 0) : nPastIndex(nPastIndex){ this->size = strlen(str); char NewStr[this->size+1]; strncpy(NewStr, str, this->size); this->str = NewStr; } 

here in this->str = NewStr; The pointer to the stack variable is copied. What will be there - after exiting the function - is a difficult question.

At a minimum, need to rewrite so

 Substring(const char *str = "", size_t nPastIndex = 0) : nPastIndex(nPastIndex){ this->size = strlen(str); this->str = new char[this->size+1]; strncpy(this->str, str, this->size); this->str[size] = '\0'; } 

And still it is necessary not to forget to release memory in destructors.

 ~Substring(){delete[] this->str;} String::~String(){ delete[] this->str;} 

After such manipulations, valgrind no longer curses and there are no leaks. The conclusion seems to be similar to the truth. But you know better what it should do. But this does not mean that there are no more errors in the code.

If you now uncomment the above line, the output "does not spoil." The only thing I added was <<std::endl .

PS If you write to c ++ and do not use API functions that require tricky strings, use regular std :: string and do not allocate memory using new (and even more so malloc).

  • Fixed, it all worked. Wow! And this "valgrind" helps out, as I see it. My tab is open from yesterday to read about this miracle. I think that I could save myself a lot of time if I had looked at the information about the utility earlier. Thank you so much, buddy. Now I can sleep well, because I spent the whole night to find a mistake and eventually turned here. All beaver. Problem solved. - Ligvest O

You have problems almost everywhere (no destructor, no copy constructor, open class fields).

You did not Substring code for the String and Substring , and I suspect that you simply copy the passed pointer into the internal field. If this is the case, then you save the pointer to the array allocated on the stack ( char SecStr[nTemp+1]; ) after exiting the function - this is a disaster.

Then, the code is strncpy(SecStr, str, nTemp); - this is also a disaster: you copy uninitialized memory (this is prohibited) by a pointer, without checking the size of the memory available there. That is, you have pointers to random chunks of memory for which you write random data. This code can not work.

Adding an extra operation can erase your incomprehensible where the underlying data, and that leads to problems. But the problem is not cout , the problem is memory management.

  • Thanks for the comment. I now understand that this behavior was just due to improper use of the stack. Useful lesson for the future. - Ligvest O
  • @LigvestO: Please! C ++ is an unsafe language, any error can affect it at any time, and usually affects it later on in an “inexplicable way”. (This is one of the reasons why it is probably the most difficult of all popular languages.) - VladD
  • But you feel special when you are one of the C ++ programmers. :) - Ligvest O
  • @LigvestO: Yes! :-) - VladD