Debug Assertion Failed ! Can someone help me understand what am i doing wrong ? 'C' language

Hello.. I get this error message while my game (program) is running. Is not happening all the time.. but sometime in a while this error appear and somehow I see that a save.txt file is deleted.. NO IDEA why.. and I suppose that when the program tries to load info of the player is not finding the file and that's probably the true reason.

The error says.. Expresion: Stream != nullptr
File: minkernel\crt\ucrt\src\appcrt\stdio\output.cpp Line:34
And I have 3 options Ignore Abort or Retry to Debug the app.

I use 'C' language. and my IDE is Microsoft visual Studio latest version.
This is how I save the info from the game
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
  void SaveCurrentUser(char* tmp)
{
	int empty = -1;
	FILE* file_save = NULL; // File.save -> Player file properties
	size_t size = strlen(tmp) + 5;
	char* fileName = (char*)malloc(size);
	fileName[size - 1] = '\0';

	strcpy_s(fileName, size, tmp);
	strcat_s(fileName, size, ".txt");
	file_save = fopen(fileName, "r");

	if (file_save != NULL) // If the file exist
	{
		fclose(file_save); // closing file for read
		remove(fileName); // delete current file and creat it again, with the new values
		file_save = fopen(fileName, "a+"); // reopen file for append+ attribute

		// Save player's attribute and items from game slots if any ... otherwise pass -1 (empty)
		fprintf_s(file_save, "Level\t\t%d\nCurrentExperience\t%d\nNextExperience\t%d\nStatPoints\t\t%d\n"
				  "SkillPoints\t\t%d\nLife\t\t%d\nMana\t\t%d\nStamina\t\t%0.0f\nStrength\t\t%d\nDexterity\t\t%d\n"
				  "Vitality\t\t%d\nEnergy\t\t%d\nFireRes\t\t%d\nColdRes\t\t%d\nLightningRes\t%d\n"
				  "PoisonRes\t\t%d\nDefense\t\t%d\nGold\t\t%d\nChanceMagicItems\t%d\nMinDamage\t%d\n"
				  "MaxDamage\t%d\n\n",
				  Player.Level, Player.CurrentExperience, Player.NextExperience, Player.StatPoints,
				  Player.SkillPoints, Player.MaxValueHP, Player.MaxValueMP, Player.MaxStamina, Player.Strength,
				  Player.Dexterity, Player.Vitality, Player.Energy, Player.FireRes, Player.ColdRes,
				  Player.LightningRes, Player.PoisonRes, Player.Defense, Player.Gold, Player.ChanceMagicItems,
				  Player.MinDamage, Player.MaxDamage);

		// Save Belt items
		for (int i = 0; i < MAX_NO_BELT_EQUIPED_SLOTS; i++)
		{
			for (int j = 0; j < MAX_GAME_ITEMS; j++)
			{
				if (Inventory.BeltSlots[i] != -1)
				{
					if (Inventory.BeltSlots[i] == GameItems[j].ItemIndex)
					{
						fprintf_s(file_save, "BeltSlot%d\t\t%d\n", i, GameItems[j].ItemIndex);
						break;
					}
				}
				else if (Inventory.BeltSlots[i] == -1)
				{
					fprintf_s(file_save, "BeltSlot%d\t\t%d\n", i, empty);
					break;
				}
			}
		}

		fprintf_s(file_save, "\n");

		// Save Hero items
		for (int i = 0; i < MAX_HERO_SLOTS; i++)
		{
			for (int j = 0; j < MAX_GAME_ITEMS; j++)
			{
				if (Inventory.PlayerEquipSlots[i] != -1)
				{
					if (Inventory.PlayerEquipSlots[i] == GameItems[j].ItemIndex)
					{
						fprintf_s(file_save, "HeroSlot%d\t\t%d\n", i, GameItems[j].ItemIndex);
						break;
					}
				}
				else if (Inventory.PlayerEquipSlots[i] == -1)
				{
					fprintf_s(file_save, "HeroSlot%d\t\t%d\n", i, empty);
					break;
				}
			}
		}

		fprintf_s(file_save, "\n");

		// Save inventory items
		for (int i = 0; i < MAX_INVENTORY_SLOTS; i++)
		{
			for (int j = 0; j < MAX_GAME_ITEMS; j++)
			{
				if (Inventory.Slots[i] != -1)
				{
					if (Inventory.Slots[i] == GameItems[j].ItemIndex)
					{
						fprintf_s(file_save, "InventorySlot%d\t%d\n", i, GameItems[j].ItemIndex);
						break;
					}
				}
				else if (Inventory.Slots[i] == -1)
				{
					fprintf_s(file_save, "InventorySlot%d\t%d\n", i, empty);
					break;
				}
			}
		}

		fprintf_s(file_save, "\n");

		// Save Private chest items
		for (int i = 0; i < MAX_PRIVATE_CHEST_SLOTS; i++)
		{
			for (int j = 0; j < MAX_GAME_ITEMS; j++)
			{
				if (PrivateChest.Slots[i] != -1)
				{
					if (PrivateChest.Slots[i] == GameItems[j].ItemIndex)
					{
						fprintf_s(file_save, "PrivateChestSlot%d\t%d\n", i, GameItems[j].ItemIndex);
						break;
					}
				}
				else if (PrivateChest.Slots[i] == -1)
				{
					fprintf_s(file_save, "PrivateChestSlot%d\t%d\n", i, empty);
					break;
				}
			}
		}

		fclose(file_save);
	}
	else if(file_save == NULL) // If file doesn't exist, create and save the new file
	{
		fclose(file_save); // closing file for read
		file_save = fopen(fileName, "a+"); // reopen file for append+ attribute

		// Save player's attribute and items from slots if any ... otherwise pass -1 (empty)
		fprintf_s(file_save, "Level\t\t%d\nCurrentExperience\t%d\nNextExperience\t%d\nStatPoints\t\t%d\n"
				  "SkillPoints\t\t%d\nLife\t\t%d\nMana\t\t%d\nStamina\t\t%0.0f\nStrength\t\t%d\nDexterity\t\t%d\n"
				  "Vitality\t\t%d\nEnergy\t\t%d\nFireRes\t\t%d\nColdRes\t\t%d\nLightningRes\t%d\n"
				  "PoisonRes\t\t%d\nDefense\t\t%d\nGold\t\t%d\nChanceMagicItems\t%d\nMinDamage\t%d\n"
				  "MaxDamage\t%d\n\n",
				  Player.Level, Player.CurrentExperience, Player.NextExperience, Player.StatPoints,
				  Player.SkillPoints, Player.MaxValueHP, Player.MaxValueMP, Player.MaxStamina, Player.Strength,
				  Player.Dexterity, Player.Vitality, Player.Energy, Player.FireRes, Player.ColdRes,
				  Player.LightningRes, Player.PoisonRes, Player.Defense, Player.Gold, Player.ChanceMagicItems,
				  Player.MinDamage, Player.MaxDamage);

		// Save Belt items
		for (int i = 0; i < MAX_NO_BELT_EQUIPED_SLOTS; i++)
		{
			for (int j = 0; j < MAX_GAME_ITEMS; j++)
			{
				if (Inventory.BeltSlots[i] != -1)
				{
					if (Inventory.BeltSlots[i] == GameItems[j].ItemIndex)
					{
						fprintf_s(file_save, "BeltSlot%d\t\t%d\n", i, GameItems[j].ItemIndex);
						break;
					}
				}
				else if (Inventory.BeltSlots[i] == -1)
				{
					fprintf_s(file_save, "BeltSlot%d\t\t%d\n", i, empty);
					break;
				}
			}
		}

		fprintf_s(file_save, "\n");

		// Save Hero items
		for (int i = 0; i < MAX_HERO_SLOTS; i++)
		{
			for (int j = 0; j < MAX_GAME_ITEMS; j++)
			{
				if (Inventory.PlayerEquipSlots[i] != -1)
				{
					if (Inventory.PlayerEquipSlots[i] == GameItems[j].ItemIndex)
					{
						fprintf_s(file_save, "HeroSlot%d\t\t%d\n", i, GameItems[j].ItemIndex);
						break;
					}
				}
				else if (Inventory.PlayerEquipSlots[i] == -1)
				{
					fprintf_s(file_save, "HeroSlot%d\t\t%d\n", i, empty);
					break;
				}
			}
		}

		fprintf_s(file_save, "\n");

		// Save inventory items
		for (int i = 0; i < MAX_INVENTORY_SLOTS; i++)
		{
			for (int j = 0; j < MAX_GAME_ITEMS; j++)
			{
				if (Inventory.Slots[i] != -1)
				{
					if (Inventory.Slots[i] == GameItems[j].ItemIndex)
					{
						fprintf_s(file_save, "InventorySlot%d\t%d\n", i, GameItems[j].ItemIndex);
						break;
					}
				}
				else if (Inventory.Slots[i] == -1)
				{
					fprintf_s(file_save, "InventorySlot%d\t%d\n", i, empty);
					break;
				}
			}
		}

		fprintf_s(file_save, "\n");

		// Save Private chest items
		for (int i = 0; i < MAX_PRIVATE_CHEST_SLOTS; i++)
		{
			for (int j = 0; j < MAX_GAME_ITEMS; j++)
			{
				if (PrivateChest.Slots[i] != -1)
				{
					if (PrivateChest.Slots[i] == GameItems[j].ItemIndex)
					{
						fprintf_s(file_save, "PrivateChestSlot%d\t%d\n", i, GameItems[j].ItemIndex);
						break;
					}
				}
				else if (PrivateChest.Slots[i] == -1)
				{
					fprintf_s(file_save, "PrivateChestSlot%d\t%d\n", i, empty);
					break;
				}
			}
		}

		fclose(file_save);
	}
}
And this is how I load info from the file
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
   void SelectExistingUser(void)
{	
	FILE* file_list = NULL; // File.txt  -> File with player name list
	FILE* file_load = NULL; // File.txt  -> File with the player's properties
	char* fListName = "PlayerList.txt"; // file list buffer
	char tmp[8] = { 0 };
	
	// Open the file_list for reading... the one that contains the players names.
	file_list = fopen(fListName, "r"); 

	// For now we open the the only save file we have..
	// We don't have implemented yet a menu with the list of the players.
	fgets(tmp, sizeof(tmp), file_list);

	// close the file_list
	fclose(file_list);

	// remove the new line at the end of the string.
	int len = strlen(tmp);
	if (len[tmp - 1] == '\n')
		len[tmp - 1] = '\0';

	// Copy tmp buffer to the player name that will show in the window character screen.
	strcpy_s(Player.Name, sizeof(tmp), tmp);
	
	// allocate memory to the buffer size + 5 for the extension and null the terminator character
	size_t size = strlen(tmp) + 5;
	char* fileName = (char*)malloc(size);
	fileName[size - 1] = '\0';

	// Copy the string from the buffer into fileName for opening the file_load with the same name from the list.
	strcpy_s(fileName, size, tmp);

	// concatenate the extension .txt to the fileName
	strcat_s(fileName, size, ".txt");

	int value = 0;
	int storage[VAR_LIST] = { 0 }; // VAR_LIST is the number of the arguments we save in the file

	file_load = fopen(fileName, "r"); // Open the player's file properties for reading.

	for (int i = 0; i < VAR_LIST && fscanf(file_load, "%*s %d", &value) != EOF; i++)
	{
		storage[i] = value;
	}

	// Assign values to the player attributes-------------|
	Player.Level						= storage[0];
	Player.CurrentExperience			= storage[1];
	Player.NextExperience				= storage[2];
	Player.StatPoints					= storage[3];
	Player.SkillPoints					= storage[4];
	Player.MaxValueHP					= storage[5];
	Player.MaxValueMP					= storage[6];
	Player.MaxStamina					= storage[7];
	Player.Strength						= storage[8];
	Player.Dexterity					= storage[9];
	Player.Vitality						= storage[10];
	Player.Energy						= storage[11];
	Player.FireRes						= storage[12];
	Player.ColdRes						= storage[13];
	Player.LightningRes					= storage[14];
	Player.PoisonRes					= storage[15];
	Player.Defense						= storage[16];
	Player.Gold							= storage[17];
	Player.ChanceMagicItems				= storage[18];
	Player.MinDamage					= storage[19];
	Player.MaxDamage					= storage[20];

	// Assign next 4 storage[X] to Belt slots ------------|
	for (int i = 0; i < MAX_NO_BELT_EQUIPED_SLOTS; i++)
	{
		Inventory.BeltSlots[i] = storage[21 + i];
	}
	// Assign next 10 storage[X] to Hero slots -----------|
	for (int i = 0; i < MAX_HERO_SLOTS; i++)
	{
		Inventory.PlayerEquipSlots[i] = storage[25 + i];
	}
	// Assign next 12 storage[X] to Inventory slots ------|
	for (int i = 0; i < MAX_INVENTORY_SLOTS; i++)
	{
		Inventory.Slots[i] = storage[35 + i];
	}
	// Assign next 42 storage[X] to Private Chest slots --|
	for (int i = 0; i < MAX_PRIVATE_CHEST_SLOTS; i++)
	{
		PrivateChest.Slots[i] = storage[47 + i];
	}
	//----------------------------------------------------|

	fclose(file_load); // Close the file pointer.

	// Assign attributes from the file to game attributes.
	Global_HP = Player.MaxValueHP;
	Global_MP = Player.MaxValueMP;
	Global_Stamina = Player.MaxStamina;
	Global_MinDamage = Player.MinDamage;
	Global_MaxDamage = Player.MaxDamage;
	Global_Defense = Player.Defense;
	Global_FireRes = Player.FireRes;
	Global_ColdRes = Player.ColdRes;
	Global_LightningRes = Player.LightningRes;
	Global_PoisonRes = Player.PoisonRes;
	Global_Strength = Player.Strength;
	Global_Dexterity = Player.Dexterity;
	Global_Vitality = Player.Vitality;
	Global_Energy = Player.Energy;
}
Is there something that has to do with the "fprintf_s" version and not the "fprintf" instead ?
One particular thing when I get the error the VS opens the stdio header and points me to the line 1024 or something where the function vfscanf_s is .. and if I point my cursor over the 'Format' argument I see that the format argument is the same one I use at the line 42 in my SeleectExistingUser function "%*s %d".. this has to do something why do I get the error ??
Because I think i use it in the right way.. avoiding the string and get only the integer, because that is only I need.
First off, you need to refactor your 200+ line function.
It's impossible to work with.

> The error says.. Expresion: Stream != nullptr
Which means you opened a file, didn't check the result, and tried to use it in some other function.

> And I have 3 options Ignore Abort or Retry to Debug the app.
Choose debug every time.

> File: minkernel\crt\ucrt\src\appcrt\stdio\output.cpp Line:34
That's where the problem was detected.
You should have an option in the debugger to "show stack trace".
Use that to navigate the call stack to the most recent function in your code.
Then start to examine all the relevant variables.

My guess is your fopen returned a NULL you're not checking for.
Yup.. I was to write that .. I have to reduce the lines number.. and yahhh.. I know that can be done more elegant way.
And yep what you are saying is true.. my question is that .. in the moment i get the error. In the game I'm not moving at all .. so no action is taken.. The file.txt is only open when i move items in the inventory and when I press manually F5 which I implemented to save the game. Otherwise the game is not saving or loading anything.
Hmm ... maybe I have one mistake which is.. I set the game to save automatically every 5 minutes. but even that.. if I'm not doing any actions.. the program can do that without any problems.

Okay.. salem c ..thank you for your answer.. I'll check the show stack trace option.. I was working with Code::Blocks ,.. and I'm new to MVS.. I'm not that familiar with.. so I'll search for it.
It's good practice to always check the return value/error code for an error - even if not expected.

eg When you use malloc/calloc in c you always check that the returned value is not NULL. Same for strcpy_s et al that can return an error. etc etc etc.

OMG.. I think I found something.. I believe that's the problem. I called the SaveCurrentUser function few times somewhere in the code, where it is permanently called .. so this function delete and remake the file again and again every fraction of a second.. I believe that's the problem.
I just comment all the SaveCurrentUser that are permanently called and now all seems to work just fine.
Thanks for answering me guys.. I'll keep in mind this next time. Cheers :)
Topic archived. No new replies allowed.