0

I have this program which works fine. But if I comment out a cout statement (see code below) it throws the error. It tried this on ideone too with same result.

Code:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;

    vector<int> ugly_numbers = vector<int>(n, 0);
    ugly_numbers[0] = 1;
    int ugly2 = 0, ugly3 = 0, ugly5 = 0, ugly_count = 1;

    while (ugly_count <= n) {
        int next_ugly_num_2 = ugly_numbers[ugly2] * 2;
        int next_ugly_num_3 = ugly_numbers[ugly3] * 3; 
        int next_ugly_num_5 = ugly_numbers[ugly5] * 5; 
        int next_ugly_num = min(min(next_ugly_num_2, next_ugly_num_3), next_ugly_num_5);
        
        if (next_ugly_num == next_ugly_num_2) ugly2++;
        if (next_ugly_num == next_ugly_num_3) ugly3++;
        if (next_ugly_num == next_ugly_num_5) ugly5++;
        //cout << ugly_count << " - ";             //*********THIS COUT IS WIERD**********
        ugly_numbers[ugly_count] = next_ugly_num;
        ugly_count++;
    }
    cout << ugly_numbers[n - 1] << endl;

    return 0;
}

Error:

a.out: malloc.c:2401: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
The terminal process "/bin/bash '-c', ' g++ -g Cpp/a.cpp -o a.out && clear && timeout 10 /usr/bin/time -v --output sys.txt ./a.out < input.txt > output.txt && rm *out'" terminated with exit code: 134.

Why is this happening? Why is this cout statement affecting the behaviour of the program? And how do I correct it?

chqrlie
  • 98,886
  • 10
  • 89
  • 149
corvo
  • 448
  • 6
  • 17
  • 4
    `while(ugly_count <= n){` puts you one past the end of the vector. – Retired Ninja Sep 26 '20 at 01:28
  • @RetiredNinja why does it work fine when the cout statement is uncommented? – corvo Sep 26 '20 at 01:30
  • 3
    @corvo Undefined behavior. It is not working. – PaulMcKenzie Sep 26 '20 at 01:30
  • @PaulMcKenzie I am new to c++. yeah it is undefined, but it is consistently working when the cout is used. And consistently crashing when its commented out – corvo Sep 26 '20 at 01:32
  • It also consistently doesn't work, no matter what I do, if I run this in the debug mode of Visual Studio. See what undefined behavior does? Also, if you used the vector's `at()` function instead of `[ ]` to access the elements, your program will throw an exception, no matter what is done. Welcome to the world of C++. – PaulMcKenzie Sep 26 '20 at 01:33
  • @RetiredNinja spot the point. Changing it to ` – Louis Go Sep 26 '20 at 01:38
  • @PaulMcKenzie I tried it on ideone. see this https://ideone.com/OAkx45 – corvo Sep 26 '20 at 01:38
  • 4
    "Undefined behavior" means anything can happen: the program crashes, the programs runs apparently without any harm, or anywhere in between, including [demons flying out of your nose](http://www.catb.org/jargon/html/N/nasal-demons.html). In your case, demons flying out of your nose make your program crash when the `std::cout` statement gets compiled, but don't bother you when it's not. – Sam Varshavchik Sep 26 '20 at 01:39
  • Do not depend on undefined behavior because your code might be broken after compiler version changed or any other lines added. – Louis Go Sep 26 '20 at 01:39
  • 4
    If adding/removing (or commenting out) an output statement changes behaviour of a program, it means that some other code is tromping memory it shouldn't - in this case, by accessing a vector element past the end. Adding an output statement changes the memory layout of the program as a whole, so can have a side-effect of changing what is stored in the tromped memory, and therefore change the symptoms of tromping it. – Peter Sep 26 '20 at 01:39
  • 1
    @corvo -- [See this](http://coliru.stacked-crooked.com/a/edaa15267306ddc5). Believe me, there are C++ programs out there in the industry right now that have these bugs, but the programmer's are not aware that they exist (until they make code changes, change compiler, etc). – PaulMcKenzie Sep 26 '20 at 01:39
  • it works fine for me in both cases, but obviously there are some bad programming in the code. you are trying to access elements of vector which you never filled – AKL Sep 26 '20 at 01:40
  • Essentially a duplicate of [Why does removing 'cout' from my function change its result?](https://stackoverflow.com/questions/17802349/why-does-removing-cout-from-my-function-change-its-result); undefined behavior is undefined. – ShadowRanger Sep 26 '20 at 01:41
  • 3
    @AKL - That is the joy of undefined behaviour. The symptoms can be completely different for different people - depending on what compiler they use, what optimisation settings, what programs are running at the same time, what memory is available or free on the system, phase of the moon, and a bunch of other contributors. – Peter Sep 26 '20 at 01:42
  • @Peter Yes you are right. – AKL Sep 26 '20 at 01:43
  • @Peter if what you're saying is true then that is what I was asking. I get it that my program is accessing out of array index but my doubt was that Why was it working when using the cout? I had the impression that print statements doesn't affect the execution of the program. Guess I was wrong. Welcome to c++ indeed – corvo Sep 26 '20 at 01:43
  • @corvo , many things depend on the OS and compiler, perhaps cout was fixing those memory which was illegally accessed! I don't think it worth our time to spend on how undefined behaviors are! Each setup has its own reaction – AKL Sep 26 '20 at 01:47
  • @corvo , BTW I suggest you to delete this post before getting more down-votes. Remember that if someone writes an answer then you can't delete your question and you will loose reputation! – AKL Sep 26 '20 at 01:51
  • @corvo - By definition, an output statement affects execution of a program - it is implemented using machine instructions that access some program data and copy a representation of that data somewhere (e.g. to the output device or file). The only difference is whether the effect on execution is observable, and whether some other code (intentionally or not) affects what is being output or (in worst cases, that some operating systems are designed to prevent) overwrite the instructions that do the output. – Peter Sep 26 '20 at 01:58
  • **Recommended reading:** [Why should I not #include ?](https://stackoverflow.com/q/31816095/560648) – Asteroids With Wings Sep 26 '20 at 02:27
  • @Peter It's not necessarily something "tromping memory" when that happens. It is in this particular case, but compilers are complex beasts and other forms of UB can have just as strange results (think "optimizations"). – Asteroids With Wings Sep 26 '20 at 02:28
  • @AsteroidsWithWings - While that's true, if given a symptom "I added a simple output statement with no side-effects and the program stopped crashing", the first thing I will do is review other code in the program to determine if any is tromping memory. I might be wrong sometime but, if I was to give you $1 for every time the problem turned out to be something else, and you were to give me $1 every time the problem turned out to be tromping of memory, you would be giving me more money over time than I'll be giving you. The odds are simply in my favour. – Peter Sep 26 '20 at 07:26
  • @Peter I think you've misunderstood me. Yes, overruns _are_ probably the most common error people make in this category that lead to UB, and "I added a simple output statement with no side-effects and the program stopped crashing" is absolutely a signal that you almost certainly have UB. But that doesn't necessarily involve "tromping memory" at runtime - the compiler can lead you astray with a bug like that long before runtime. UB is more complicated than this. C++ is an abstraction: you're not programming a computer; you're _describing a program_. Programming a computer is the compiler's job. – Asteroids With Wings Sep 26 '20 at 13:38

1 Answers1

0

You have an undefined behavior in the last loop iteration when you modify ugly_numbers[ugly_count] with ugly_count equal to n. This undefined behavior may or may not be visible: it depends on the value of n, on how vector is implemented, and many other improbable factors. This may explain why you only get an error without the output statement.

You should run the loop from 0 to n excluded or make the vector one element larger:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;

    vector<int> ugly_numbers = vector<int>(n + 1, 0);
    ugly_numbers[0] = 1;
    int ugly2 = 0, ugly3 = 0, ugly5 = 0;

    for (int ugly_count = 1; ugly_count <= n; ugly_count++) {
        int next_ugly_num_2 = ugly_numbers[ugly2] * 2;
        int next_ugly_num_3 = ugly_numbers[ugly3] * 3; 
        int next_ugly_num_5 = ugly_numbers[ugly5] * 5; 
        int next_ugly_num = min(min(next_ugly_num_2, next_ugly_num_3), next_ugly_num_5);
        
        if (next_ugly_num == next_ugly_num_2) ugly2++;
        if (next_ugly_num == next_ugly_num_3) ugly3++;
        if (next_ugly_num == next_ugly_num_5) ugly5++;
        //cout << ugly_count << " - ";
        ugly_numbers[ugly_count] = next_ugly_num;
    }
    cout << ugly_numbers[n - 1] << endl;

    return 0;
}
chqrlie
  • 98,886
  • 10
  • 89
  • 149