0

I played with the string function,i wrote the following one, obviously I set the first character in the ret string to be written in a place that is out of bounds, but instead of an exception, I get a string that has one extra place .

std::string StringManipulations::rev(std::string s)
{
    
    std::string ret(s.size(), ' ');

    for (int i = 0; i < s.size(); i++)
    {
        std::string ch;
        ch.push_back(s[i]);
        int place = s.size() -i;
        ret.replace(place,1,ch);
    }
    return ret; 
}

I write by mistake in a position that corresponds to a place that is one larger than the original string size that I assign at the beginning of the function.

Why don't we get an error ?

s = StringManipulations::rev("abcde");
    std::cout << s.size();
    std::cout << s;

output is : 6 _edcba 

any help ?

solved: adding ch as a String adds a null terminator automatically, and by doing so we can get a new string with size+1.

  • 2
    Going out of bounds leads to *undefined behavior*. It might cause a crash, it might seem to work, or it might summon [nasal demons](http://www.catb.org/jargon/html/N/nasal-demons.html). – Some programmer dude Oct 24 '21 at 08:23
  • It might help: https://stackoverflow.com/questions/671703/array-index-out-of-bound-behavior – Mojtaba Valizadeh Oct 24 '21 at 08:24
  • Yes, thanks for the reply .. strange that as soon as the difference is greater than 1 exception is there otherwise we get a new string that has a size +1. – Nemanja Pavlovic Oct 24 '21 at 08:29
  • Probably, it is because that a string is an array of chars that has an extra char at the end like "\0" to show that this is the end of the string. It might help: https://www.tutorialspoint.com/cprogramming/c_strings.htm – Mojtaba Valizadeh Oct 24 '21 at 09:00
  • 1
    Off-topic side note: The function looks ugly in terms of both efficiency and readability. Why not (e.g.) `ret[s.size() - i - 1] = s[i];`? Also, if this wasn’t a manual string reversal exercise, I would use `return std::string{s.rbegin(), s.rend()};` or, because you already copy `s` anyway (i.e. pass it by value), why not avoid yet another copy: `std::reverse(s.begin(), s.end()); return s;`. – Andrej Podzimek Oct 24 '21 at 09:26
  • With GCC you may get the following runtime error message: "terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::replace: __pos (which is 18446744073709551615) > this->size() (which is 5)" – QuentinUK Oct 24 '21 at 10:27
  • the code is not optimized in this way because the behavior is not identical ... this happened by accident, so I kept it because of this behavior ....size +1 in return value thing ...thats not happening in this case ret[s.size() - i ] = s[i]; – Nemanja Pavlovic Oct 24 '21 at 10:28

2 Answers2

0

C++ has a zero-overhead rule. This means that no overhead, (like checking if an index is in-bounds) should be done unintentionally. You don't get an exception because c++ simply doesn't verify if the index is valid.

For the extra character, this might have something to do with (regular) c strings. In c, strings are arrays of type char (char*) without a defined size. The end of a string is denoted with a null terminator. C++ strings are backwards compatible, meaning that they have a null terminator too. It's possible that you replaced the terminator with an other character but the next byte was also a zero meaning that you added one more char.

StackOverflower
  • 526
  • 3
  • 14
  • 1
    yes, my suspicion is same, i think it added a character to the terminator position and then the terminator was subsequently added automatically to the end of the string and so we got a valid string with one more space. – Nemanja Pavlovic Oct 24 '21 at 08:37
0

In addition to the information above about null terminators, another answer to your question is that the docs says it will only throw if the position is greater than the string size, rather than beyond the end of the string. string replace api

eahsi
  • 36
  • 1