Блог пользователя LLI_E_P_JI_O_K

Автор LLI_E_P_JI_O_K, история, 7 лет назад, По-русски

Hello, guys!

Today in Codeforces round 402 (Div 2) I tried to challenge this solution with a test:

5 2
1 1 1 1 1
5 5 5 5 5

So, as you can see in the code this cycle has no any check for reaching the end of the vector "v":

...
while (v[j].first<0||j<r)
{
sum1+=v1[v[j].second];
j++;    
}
...

Obviously "j" will be out of the vector for such testcase and we will check whether "v[5].first<0" or not, but no any Runtime Error when trying to get nonexistent element of vector. So, as you can understand, challenge was unsuccessful. Why?

  • Проголосовать: нравится
  • +13
  • Проголосовать: не нравится

»
7 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Usually std::vector preallocates more memory than you need, so amortized cost of vector::push_back was O(1).

You can check what's std::vector::capacity() is. Depending on implementation it could be different. E.g. if capacity() == size() and we want to insert a new element, new capacity() will likely be either 1.5 * size() or 2 * size().

So that's likely the case here.

  • »
    »
    7 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Yes, but as I thought, if we try to get element with index >= current size of vector via operator [], then an exception should be thrown and immediately we should get Runtime Error. Isn't it?

    • »
      »
      »
      7 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      No, it's only happens when you use std::vector::at(idx). In case of operator[] no boundary checks are performed, so it's likely to be an undefined behaviour.

      • »
        »
        »
        »
        7 лет назад, # ^ |
          Проголосовать: нравится +5 Проголосовать: не нравится

        Ok, that's a pity. How to challenge such solutions? They obviously contain error. I met one more such solution in my room today, but didn't try to challenge, because it would be unsuccessful too :(

        • »
          »
          »
          »
          »
          7 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          If it's + small constant out of boundary of std::vector I wouldn't risk.

          Even so in this case it has some garbage in index >= current_size elements it's hard to predict what exactly we have there. It can be a positive value and everything will work. So to challenge the solution you probably need a few attempts.

          Although if it has more limited range check for a value like: l <= vec[out_of_boundary] && vec[out_of_boundary] <= r and r - l is very small, then you can try it =).

»
7 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

You need size to be a large power of 2. 1024 is minimal sufficient to crash this solution.

  • »
    »
    7 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    Even if the accessed element will be out of the reserved capacity of the vector it might not crash anyway. And you can't guess what garbage will be there. So it's not sufficient.

»
7 лет назад, # |
  Проголосовать: нравится +7 Проголосовать: не нравится

Difference between operator[] and method at() is that operator[] has no bounds checking. So you can use elements which are not logically existent, but physically they are. I mean, it just a place in RAM — so if it is valid, you can use it, but you cant be sure if it is not used by another piece of code or even another program.

Runtime error appears when you are trying to get element by invalid address. It may cause if you are getting element of vector<vector<T> > by using [i][j] with invalid i. In this case it is possible to get invalid pointer by asking this from nonexistent vector<T>.