andreasjoerg andreasjoerg - 10 days ago 5
C++ Question

.c_str() doesn't behave as expected

I want to create a process to read out some serial port. However the user should be able to change the path where the program is located in the future. This is why I would like to include the variable BasePathFile, which is set to the default value durin the initialization of the class:

const std::string BP = "C:\\aerospec_developement\\";
...
BasePathFile = BP;
...


Can someone explain why //1 doesn't work, but //2 is fine

void AerospecGUI::ReadPressure()
{
//1 const char *Args = ("C:\\Windows\\System32\\cmd.exe /C powershell /C "+ BasePathFile+"sourcecode\\pressure.ps1 -comport COM4 -baud 1200 -parity None -data 8 -stopbits one").c_str();
//2 const char *Args = "C:\\Windows\\System32\\cmd.exe /C powershell /C C:\\aerospec_developement\\sourcecode\\pressure.ps1 -comport COM4 -baud 1200 -parity None -data 8 -stopbits one";

STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
memset(&StartupInfo, 0, sizeof(StartupInfo));
memset(&ProcessInfo, 0, sizeof(ProcessInfo));
StartupInfo.cb = sizeof(StartupInfo);
wchar_t wargs[1000];
mbstowcs(wargs, Args, strlen(Args)+1);//Plus null
LPWSTR argsptr = wargs;

bool result = CreateProcess(NULL, argsptr, NULL, NULL, FALSE, NULL, NULL, NULL,
&StartupInfo, &ProcessInfo);
...


Further, the author wrote a very similar line in another function. But this one worked.

bool AerospecGUI::FTP(std::string command, std::string file)
{
// This function executes a batch script with the given parameters. The batch script
// generates a .ftp file which contains the commands to perform the action given by "command"
// (get, put, delete).
const char *Args = ("C:\\Windows\\System32\\cmd.exe /C "+BasePathFile +"FTP\\FileTransfer.bat " + ServerURL + " root password " + command + " " + BasePathFile + "FTP\\ " + file +" " + BasePathFile + "FTP\\" + file.substr(0,file.size()-4)+".ftp").c_str();
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
memset(&StartupInfo, 0, sizeof(StartupInfo));
memset(&ProcessInfo, 0, sizeof(ProcessInfo));
StartupInfo.cb = sizeof(StartupInfo);
wchar_t wargs[1000];
mbstowcs(wargs, Args, strlen(Args)+1);//Plus null
LPWSTR argsptr = wargs;
...

Answer

1 and the original author code are wrong: c_str() returns a pointer to a C-like string, but it's a member function of the std::string class (see docs). Dereferencing its pointer after the std::string object has expired is undefined behavior (may or may not work).

2 works fine instead

const char *Args = "C:\\... one";

since it's a string literal and its lifetime spans for the entire program execution.