assert C++ (Problem understanding the code)

I have problem understanding this code. I don't understand what is going on from assert code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 void append(int x) {
       if (size >= capacity) {
          capacity = 2 * capacity;          // double the capacity
          int* new_arr = new int[capacity]; // make new underlying array
                                            // twice size of old one

          for(int i = 0; i < size; ++i) {   // copy elements of v
             new_arr[i] = arr[i];           // into new_arr
          }

          delete[] arr;                     // delete old arr

          arr = new_arr;                    // assign new_arr
       }

       // What happens after here ?
       assert(size < capacity);
       arr[size] = x;
       size++;
   }
You've double-posted this. On line 17 if size is greater than or equal to capacity, the program is aborted. This could conceivably happen if line 3 resulted in overflow, in which case the loop on line 7-9 would result in undefined behavior prior to the sanity check, although I would expect line 4 would probably result in an exception being thrown prior to that happening.
what is going on from assert code

assert imposes a run-time check on the program, if it fails the program aborts. a simple example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <cassert>

int main()
{
   int a{}, b{};
   std::cin >> a >> b;
   assert(a > b);
}
//Output
/* 
1
2
Assertion failed: a > b, file test0.cpp, line 8

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Process returned 255 (0xFF)   execution time : 6.629 s
Press any key to continue.*/

The following link might also be of interest:
http://stackoverflow.com/questions/18210270/what-is-the-difference-between-assert-and-static-assert
@cire, after carefully observing the code, and performing few tests. I realized that everything after the assert ( ) gets printed out because

1
2
3
if (size >= capacity){
// resize capacity ...
}


if size is greater than capacity, then the if statement will resize the capacity. If size is smaller than the capacity. Then it will still be true for

 
assert(size < capacity)


which will still allow the later codes to be performed.

Am I right with my logic ?

Here is the test code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Example program
#include <iostream>
#include <cassert>
#include <cstdlib>

using namespace std;

class test{

    private: 
    int capacity;
    int size;
    int* arr;
    
    public:
    test()
    :capacity(10), size(11), arr(new int[capacity])
    {}
    
  
    void append(int x) {

       if (size >= capacity) {
          capacity = 2 * capacity;          // double the capacity
          int* new_arr = new int[capacity]; // make new underlying array
                                            // twice size of old one

          for(int i = 0; i < size; ++i) {   // copy elements of v
             new_arr[i] = arr[i];           // into new_arr
          }

          delete[] arr;                     // delete old arr
          arr = new_arr;                    // assign new_arr
       }

       // What happens after here ?
       assert(size < capacity);
       cout << "Later code will print out" << endl;
       arr[size] = x;
       size++;
   }

};
int main()
{
    
    test x;
    x.append(5);
    
    return 0;
}


@gunnerfunner, thank you for your helpful example, it was really easy to understand.
Last edited on
> Am I right with my logic ?

Yes. assert(size < capacity); is equivalent to

1
2
if( size >= capacity and NDEBUG is not defined ) then abort the program with a diagnostic message
else carry on normally with the next statement


An assertion is simply a logical expression that is assumed to be true. However, for an assertion to be more than a comment, we need a way of expressing what happens if it is false.
...
In <cassert>, the standard library provides the assert(A) macro, which checks its assertion, A ,
at run time if and only if the macro NDEBUG ("not debugging") is not defined. If the assertion fails, the compiler writes out an error message containing the (failed) assertion, the source file name, and the source file line number and terminates the program.
Stroustrup in 'The C++ Programming language (4th ed.)'


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void append(int x) {

   if (size >= capacity) { // if there is not enough space allocated to add one more item

      /*
      // this sequence of operations is not exception safe
      // new int[capacity]; may throw and we would be saddled with an invalid capacity
      capacity = 2 * capacity;          // double the capacity
      int* new_arr = new int[capacity]; // make new underlying array
                                        // twice size of old one
      */

      // we assume that the current value of capacity is non-zero (ie. it is some positive number)
      // so that if we create a buffer of size (capacity*2), it would be a larger number
      // we can assert the assumption made while writing the code. if the assertion fails
      // (if capacity == 0), capacity*2 is also zero, and our code is broken
      // very robust check may include a check to see if we can safely double the capacity.
      // if( capacity < std::numeric_limits<std::size_t>::max()/2 ) ;
      assert( capacity > 0 ) ;

      // try to make a new array twice the size of old one
      // this may throw bad_alloc or bad_array_new_length
      int* new_arr = new int[capacity*2];

      // allocation was successful, update capacity to reflect it
      capacity = 2 * capacity;

      for(int i = 0; i < size; ++i) {   // copy elements of v
         new_arr[i] = arr[i];           // into new_arr
      }

      delete[] arr;                     // delete old arr

      arr = new_arr;                    // assign new_arr
   }

   // if the code is correct up to this point, it should be possible
   // to append an item at the end without allocating a larger chunk of memory.
   // we write the rest of the code under the assumption that this assumption is true
   // if our assumption is wrong, the assertion fails (debug), and we get to know
   // that there is an error somewhere in our code; it needs to be fixed
   assert(size < capacity);

   arr[size] = x; // add the new item at the end
   size++; // increment size
}
Topic archived. No new replies allowed.