Reputation: 1
Sorry for any poor formatting - this is my first time asking a question here.
I'm working on a project which involves writing some information to a file. When I run or debug the program in debug compiler configuration (Visual Studio 2022, Windows 10), everything works perfectly. However, when I run/debug it in the release configuration, the std::ofstream at line 447 fails, and the program is std::abort()'d by the check a few lines later. I can't figure out why this is happening, especially as it works in the debug configuration.
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <Windows.h>
void write_to_file()
{
wchar_t path[256];
int path_terminus{ -1 };
std::string str_path{};
GetModuleFileName(NULL, path, 256); //finds the current path
for (int i{}; (i < 256 && i != path_terminus); ++i) //finds location of the end of the path within the string
{
if (path[i] == '\0')
{
path_terminus = i;
}
}
for (int i{ 0 }; i < (path_terminus - 20); ++i) //deletes the "\\harmonic.series.exe" from the end
{
str_path.push_back(path[i]);
}
str_path += "\\harmonic_series.txt"; //adds the filename to the path (changed from .wav to .txt for ease of reproductibility)
std::ofstream ofs(str_path, std::ios::binary); //opens the filestream
if (!ofs.is_open())
{
std::cout << "Failed to open the ofstream.\n\n";
system("pause");
std::abort();
}
ofs << "placeholder_data";
}
int main()
{
write_to_file();
return 0;
}
I'm relatively new to C++, so I have no idea why this would happen! Thanks in advance.
Upvotes: -3
Views: 97
Reputation: 1
Thanks to everybody who contributed for helping out! It turns out that in the release configuration, the empty wchar_t array isn't initialised with as the value 52428 ('쳌'), but as as mostly '\0'. Because in the debug configuration the '\0' terminator only came up exactly once (at the end of the path) before the remainder of the array was '쳌', my for loop break condition didn't work when there was more than one '\0'. The following fixed the issue:
/*earlier code */ GetModuleFileName(NULL, path, 256); //finds the current path
for (int i{}; (i < 256 && i != path_terminus && path[i - 1] != '\0'); ++i) //finds location of the end of the path within the string
{
if (path[i] == '\0')
{
path_terminus = i;
}
}
for (int i{ 0 }; i < (path_terminus - 36); ++i) //deletes the "\\harmonic.series.exe" from the end
{
str_path.push_back(path[i]);
} /* later code */
However, following @Evg's excellent suggestion about std::filesystem::path (which I didn't even know existed!), I replaced everything from the start of write_to_file() with the following:
/*earlier #includes*/
#include <filesystem>
void write_to_file()
{
wchar_t cpath[256];
GetModuleFileName(NULL, cpath, 256); //finds the current path
std::filesystem::path path(cpath);
path.replace_filename("harmonic series troubleshooting doc.txt");
std::ofstream ofs(path, std::ios::binary); //opens the filestream
if (!ofs.is_open())
{
std::cout << "Failed to open the ofstream.\n\n";
system("pause");
std::abort();
}
ofs << "placeholder_data";
}
Which also works perfectly, is much more elegant, and takes up less space - all round a far better option.
Side note (and I didn't know about this either), when you set your compiler standard (i.e. C++14, C++17 etc.), it only applies to your current configuration. This meant that what I was doing in Release was only using C++14, not C++20 like the rest of my project. This may or may not have had an impact on my issue, but is worth keeping in mind.
Upvotes: 0