1

I have a program where just having cout statements works, however, adding in a class and calling its constructor completely breaks the program. I need help figuring out what the issue is.

This code produces no output:

#include <iostream>
#include <string>

using namespace std;

#define WORDCOUNTER_DATA_LENGTH 262144
struct WordCounterDataPair{
    string Word;
    unsigned int Count;
    unsigned int Position;
};
class WordCounter{
    public:
        WordCounter(){
            cout << "constructor\n";
            for(unsigned int i = 0; i < WORDCOUNTER_DATA_LENGTH; i++){
                Words[i] = "";
                Counts[i] = 0;
            }
        };
        WordCounter(string words[WORDCOUNTER_DATA_LENGTH], unsigned int counts[WORDCOUNTER_DATA_LENGTH]){
            for(unsigned int i = 0; i < WORDCOUNTER_DATA_LENGTH; i++){
                Words[i] = words[i];
                Counts[i] = counts[i];
            }
        };
        void IncrementWord(string word){
            WordCounterDataPair search = ValueOf(word);
            if(search.Count == 0){
                Words[search.Position] = word;
                Counts[search.Position] = 1;
                Length++;
            }else{
                Counts[search.Position]++;
            }
        };
        WordCounterDataPair at(unsigned int value){
            WordCounterDataPair res;
            res.Word = Words[value];
            res.Count = Counts[value];
            res.Position = value;
            return res;
        };
    protected:
        string Words[WORDCOUNTER_DATA_LENGTH];
        unsigned int Counts[WORDCOUNTER_DATA_LENGTH];
        unsigned int Length = 0;
        WordCounterDataPair ValueOf(string word){
            for(unsigned int i = 0; i < Length; i++){
                if(Words[i] == word){
                    WordCounterDataPair res;
                    res.Word = word;
                    res.Count = Counts[i];
                    res.Position = i;
                    return res;
                }
            }
            WordCounterDataPair res;
            res.Word = "";
            res.Count = 0;
            res.Position = Length;
            return res;
        };
};

int main(){
    cout << "before\n";
    WordCounter WCTest;
    cout << "after\n";
    return 0;
}

And this code

#include <iostream>
#include <string>

using namespace std;

#define WORDCOUNTER_DATA_LENGTH 262144
struct WordCounterDataPair{
    string Word;
    unsigned int Count;
    unsigned int Position;
};
class WordCounter{
    public:
        WordCounter(){
            cout << "constructor\n";
            for(unsigned int i = 0; i < WORDCOUNTER_DATA_LENGTH; i++){
                Words[i] = "";
                Counts[i] = 0;
            }
        };
        WordCounter(string words[WORDCOUNTER_DATA_LENGTH], unsigned int counts[WORDCOUNTER_DATA_LENGTH]){
            for(unsigned int i = 0; i < WORDCOUNTER_DATA_LENGTH; i++){
                Words[i] = words[i];
                Counts[i] = counts[i];
            }
        };
        void IncrementWord(string word){
            WordCounterDataPair search = ValueOf(word);
            if(search.Count == 0){
                Words[search.Position] = word;
                Counts[search.Position] = 1;
                Length++;
            }else{
                Counts[search.Position]++;
            }
        };
        WordCounterDataPair at(unsigned int value){
            WordCounterDataPair res;
            res.Word = Words[value];
            res.Count = Counts[value];
            res.Position = value;
            return res;
        };
    protected:
        string Words[WORDCOUNTER_DATA_LENGTH];
        unsigned int Counts[WORDCOUNTER_DATA_LENGTH];
        unsigned int Length = 0;
        WordCounterDataPair ValueOf(string word){
            for(unsigned int i = 0; i < Length; i++){
                if(Words[i] == word){
                    WordCounterDataPair res;
                    res.Word = word;
                    res.Count = Counts[i];
                    res.Position = i;
                    return res;
                }
            }
            WordCounterDataPair res;
            res.Word = "";
            res.Count = 0;
            res.Position = Length;
            return res;
        };
};

int main(){
    cout << "before\n";
    cout << "after\n";
    return 0;
}

produces the output:

before
after

What is going on here? How can a class constructor even cause this? I am using g++ to compile, and I'm compiling with g++ main.cpp -o program.exe. The compiler successfully creates a program for both files above and generates no errors or even warnings.

Thanks for your help in advance.

user8385393
  • 104
  • 1
  • 9
  • Maybe the first one crashes? What does your debugger say? You're probably overflowing the stack. – HolyBlackCat Feb 06 '22 at 07:53
  • 1
    The size of your class is around 8 megabytes which is larger than the default stack size on most operating systems, use `std::vector` instead of arrays – Alan Birtles Feb 06 '22 at 07:59
  • I guess that the main surprise for you is that the string `"before"` is not seen. That is because `std::cout` buffers output. You need to flush the buffers (or use `std::endl` instead of `'\n'`). – Dmitry Kuzminov Feb 06 '22 at 08:04
  • Solution: the array is too large for the stack size; use dynamic arrays or vectors. – user8385393 Feb 06 '22 at 16:36
  • I have a smilar problem, the constructor isin't even called. The class constructor worked well until I made some changes to a method. Thinking the method was the problem, I reverted it back to what it was and it still did not work. The constructor and class definition was left unchanged, and would suddently break the program. The program doesn't exit, it waits for something, and I have to press ^c in order to break it. It is especially weird to me since nothing about the class changed except for a mehtod I now deleted. I am clearing the buffer with std::endl .Also no compiling errors. – vLev Feb 07 '22 at 15:55

1 Answers1

-1

#define WORDCOUNTER_DATA_LENGTH 262144

Issue is with the value of WORDCOUNTER_DATA_LENGTH. If you take a smaller value or do not iterate even for once, i.e. do not call the constructor(as done in second program) your program will run well. To iterate over a big value takes a lot of time and causes the program to end with no output. Try taking a smaller value and it will execute fine.

Muskan
  • 1
  • 1
  • This code will execute in a fraction of a second, 200,000 iterations of a for loop is not a big value. Even if it did take a long time the program would still eventually produce a result, there is no time limit on program execution – Alan Birtles Feb 06 '22 at 08:03
  • Yes I think you are right. But I tried with smaller value and that worked well and that's why came with this conclusion. I also faced the same issue but that value which troubled me was definitely larger than this. – Muskan Feb 06 '22 at 08:07
  • @AlanBirtles, IMHO, the main surprise was that the string `"before"` is not neen. The question you refer to doesn't explain that. – Dmitry Kuzminov Feb 06 '22 at 08:07
  • @DmitryKuzminov the stack allocation likely happens at the beginning of the function so `cout` is never called or if it is called the program crashes before the stream flushes – Alan Birtles Feb 06 '22 at 08:13
  • @Muskan a smaller value allocates less memory and fixes the stack overflow – Alan Birtles Feb 06 '22 at 08:13
  • @AlanBirtles, my point is that the question needs a deeper answer than just the one you refer to. – Dmitry Kuzminov Feb 06 '22 at 08:49
  • @DmitryKuzminov not really, it crashes, fix the crash and it'll work – Alan Birtles Feb 06 '22 at 08:53