Console application froze when something went wrong, but no errors, so I can't pinpoint the problem

For context, I've created a basic "Email Simulator" that you can use to send emails to yourself, read the emails, and delete the emails. I have to use a stack linked list-style approach in this method, that's the criteria.

So far I've found out that the issue is with the displayInbox function, but what exactly went wrong I don't know for sure, because from the knowledge I have it seems logical that it would work. However I am unable to be sure as it doesn't provide an error code or trigger the Local Windows Debugger, it just freezes.

To trigger the same error I had, just compose 2 emails and then check the inbox. It doesn't matter if you check inbox in between.
I used to be able to do it but now I couldn't.
I'm using VS2019 for reference.

I'm not very experienced so it might be very bloated, so its quite large. But I did my best to make a shortened one from more than 600 lines to around 280 lines but you can still make the error occur. And this is a pastebin link to the full program in case
https://pastebin.com/Hp3uP0B9

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#include <iostream>
#include <string>
#include <stdlib.h> 
#include <windows.h> 
using namespace std;

struct Email //just a basic struct
{	
	string data;
	
	int index{}; //every new email will have a different index, used to traverse and pinpoint the correct email.

	Email* prev{}, * next{}; //just previous and next nodes
};
Email* myTemplate() //used to initialise a struct (alternative of constructor)
{
	Email* temp = new Email;

	temp->data = "\0";

	temp->index = 0;
	temp->next = NULL;
	temp->prev = NULL;

	return temp;
};

struct UI //another basic struct, but using constructors
{
	UI* prev, * next; //previous and next nodes
	string text[2]; //stores the selected text and unselected text

	bool selected; //bool to know when to trigger selected text
	int menuFunc; //used to determine which function to call, can also be used to represent Email's index when passing in values

	UI()
	{
		prev = NULL;
		next = NULL;
		text[0] = "\0";
		text[1] = "\0";
		selected = false;
		menuFunc = -1;
	}
	UI(UI* myPrev, UI* myNext, int myMFunc, string myText)
	{
		prev = myPrev;
		next = myNext;
		menuFunc = myMFunc;
		text[0] = myText;
		text[1] = "<<" + text[0] + ">>";
		selected = false;
	}
};

int mainMenu()
{
	int temp;
	cout << "type 1 to compose email, type 2 to display inbox, type 99 to quit\n: ";
	cin >> temp;
	if (temp == 1||temp == 2||temp == 99)
	{
		return temp;
	}
	else
	{
		return mainMenu();
	}	
}

int getKeyInt() //just a function to get relevant key codes
{
	if (GetAsyncKeyState(VK_UP))
	{
		return VK_UP;
	}
	else if (GetAsyncKeyState(VK_DOWN))
	{
		return VK_DOWN;
	}
	else if (GetAsyncKeyState(VK_RETURN))
	{
		return VK_RETURN;
	}
	else if (GetAsyncKeyState(VK_ESCAPE))
	{
		return VK_ESCAPE;
	}
	else
	{
		return -1;
	}
}

void displayInbox(UI* myNavi, UI* myHead, UI* myTail, Email*& eNavi, Email*& eHead, Email*& eTail) //displays the inbox of the mail
{
	bool modified = false;
	bool tempRunFlag = true;
	int tempKeyPress;

	UI* refreshCache = myHead; // to log the navigator's location upon reprinting the screen, points to head before the loop begins

	myNavi = myHead; //points the navigator to the newest node in the list

	eNavi = eTail; //email navigator switches address to the newest node in the email linked list

	if (eNavi->data != "\0") //to check if newest mail has values, just in case
	{
		myNavi->menuFunc = eNavi->index; //assigns the email index to the "menuFunc" to be passed when calling deleteMail() and displayMail()
		myNavi->text[0] = eNavi->data;  //sets the UI text of navigator
		myNavi->text[1] = "<<" + myNavi->text[0] + ">>";
		myHead = myNavi;//setting myHead to point to navigator's current address
		myHead->selected = true; //this will trigger the selected text's output later
		refreshCache = myHead;// assigns refreshCache to myHead
		myTail = myHead; //if it's only 1 mail in the list, then this will prevent UI from traversing into NULL, if not, below will change the values

		if (eNavi->prev != NULL)//if email navigator has a earlier mail to point to, false if there's only 1 element in the list, which is already done above
		{
			while (eNavi != NULL)//if email navigator is not pointing to the earliest mail, or if theres only 1 element
			{
				if (eNavi != eHead) //double checking if email navigator hasn't reached the earliest mail yet, if it is, then no need to go even earlier
				{
					eNavi = eNavi->prev; //email navigator approaches eHead by 1 node
				}
				myNavi->next = new UI(myNavi, NULL, eNavi->index, eNavi->data); //creates a new node to point to 
				myNavi = myNavi->next; // navigator switch to the next address that it created
				myTail = myNavi; //assigns tail to newly created UI navigator node
			}
		}
	}
	else //if newest mail has no values, or no mail
	{
		myHead = new UI(NULL, NULL, 0, "nothing to see here");
		myHead->selected = true;
		refreshCache = myHead;
		myTail = myHead;
	}

	while (tempRunFlag)
	{
		system("CLS");
		cout <<
			"\nNow browsing inbox..." << endl <<
			"____________________________________________________________________________________________________" << endl <<
			"MAIL DATA"<< endl;
		myNavi = myHead; //UI navigator will be reassigned to point to first UI
		while (myNavi != NULL)
		{
			cout << myNavi->text[(int)myNavi->selected] << endl;
			myNavi = myNavi->next;
		}
		myNavi = refreshCache;//similar implementation in the prompt() function;
		if (myNavi != NULL)
		{
			cout << "\nMenu Function code: " << myNavi->menuFunc << endl;//used for debugging, displays the menuFunc
		}
		cout <<
			"\n\nReached end of inbox" << endl <<
			"____________________________________________________________________________________________________" << endl <<
			"[Use ARROW KEYS UP & DOWN to navigate, ESC to return to Main Menu]" << endl;
		system("pause");

		tempKeyPress = getKeyInt();

		switch (tempKeyPress)
		{
		case VK_UP:
			if (myNavi != myHead)
			{
				myNavi->selected = false;
				myNavi = myNavi->prev;
				myNavi->selected = true;
				refreshCache = myNavi;
			}
			break;
		case VK_DOWN:
			if (myNavi != myTail)
			{
				myNavi->selected = false;
				myNavi = myNavi->next;
				myNavi->selected = true;
				refreshCache = myNavi;
			}
			break;
		case VK_ESCAPE:
			tempRunFlag = false;
			break;
		default:
			break;
		}
	}
	return;
}

void composeEmail(Email*& eHead, Email*& eTail) //prompting the user to get data
{
	Email* draft = new Email;
	system("CLS");
	if (eHead->data != "\0") ///used to get rid of a \n character in the buffer for no reason, I don't know why it's there, but whats weird is that it only happens once the email linked list already has 1 element inside of it
	{
		cin.ignore();
	}
	do
	{
		cout << "\nPlease type in data (16 character limit)" << endl; //just for no reason
		getline(cin, draft->data);
	} while (draft->data.length() > 16 || draft->data.length() <= 0);
	while (draft->data.length() < 16)
	{
		draft->data += " ";
	}
	cout << "\n\nEmail is sent! Please check inbox." << endl;

	draft->next = NULL;
	if (eHead->data == "\0") //if current head node is empty
	{
		draft->prev = NULL;
		draft->index = eTail->index + 1;
		eHead = draft;
		eTail = eHead;
	}
	else //if head node already has a value
	{
		draft->prev = eTail;
		draft->index = eTail->index + 1;
		eTail->next = draft;
		eTail = draft;
	}

	system("pause");
}

bool mainMenuExecute(int executionCode, UI* uiNaviIB, UI* uiHeadIB, UI* uiTailIB, Email*& eNavi, Email*& eHead, Email*& eTail)
{
	if (executionCode == 1)
	{
		composeEmail(eHead, eTail);
		return true;
	}
	else if (executionCode == 2)
	{
		displayInbox(uiNaviIB, uiHeadIB, uiTailIB, eNavi, eHead, eTail);
		return true;
	}
	else if (executionCode == 99)
	{
		return false;
	}
}

int main()
{
	//Inbox UI
	UI* uiHeadIB = new UI(NULL, NULL, 0, "nothing to see here"),
		* uiTailIB = uiHeadIB,
		* uiNaviIB = uiHeadIB;
	uiNaviIB->selected = true;

	//Actual mail stuff
	Email* mHead = myTemplate(),
		* mTail = mHead;
	Email* mNavi = mHead;

	bool simulate = true;

	while (simulate)
	{
		system("CLS");
		simulate = mainMenuExecute(mainMenu(), uiNaviIB, uiHeadIB, uiTailIB, mNavi, mHead, mTail);
	}
}



Hope someone can provide constructive criticism as I get to learn more, cheers.
Last edited on
try debugging that while loop. programs 'freeze' if they get into a loop forever, so print something inside the display's while loop to see if its stuck in there. If so, figure out why and fix.
I imagine it would print out something at least because inside the while loop it has couts, but I still can't pinpoint the issue... Any tips?
Your simplified code seems to be stuck in the while (eNavi != NULL) loop of displayInbox.
Note that if eNavi equals eHead then that loop will not terminate since eNavi is not NULL and since it IS eHead, it will not get set to eNavi->prev.
Last edited on
I see! Indeed that would be the case! Much thanks! @dutch!
As you're using VS2019, I really recommend that you get to learn the debugger. VS2019 has one of the more powerful debugger. Using it will greatly help in finding issues with code. In this case using the debugger to trace through the code would have identified the issue quickly.
Topic archived. No new replies allowed.