I understand that when calling exec*()
the memory of the old process is completely replaced with the new program. However, what about the memory of the arguments such as argv? If I have code like this, is it safe to use memory from C++ data structures such as std::string
or will these potentially go away, corrupting argv
?
#include <unistd.h>
#include <string>
#include <string.h>
#include <vector>
#include <iostream>
void
execExample(const std::vector<std::string> &arguments)
{
char **argv = new char *[arguments.size() + 2];
char *path = "/path/to/my/executable";
unsigned int idx = 0;
argv[idx] = path;
for (; ++idx < arguments.size() + 1; ) {
argv[idx] = const_cast<char *>(arguments[idx - 1].c_str());
}
argv[idx] = 0;
execv(path, argv); // Does not return if successful.
std::cerr << "exec failed: " << strerror(errno) << ".\n";
}
From the execv
man page:
The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer. [Emphasis added]
So, you provide a null terminated array of null terminated C strings. The man page doesn't explicitly say what happens to the memory, but presumably the strings are copied, as though by a strcpy
, to the new process, and the new pointers are provided to the main
of the new process. Because execv
can't possibly know anything contextual about those strings (are they static? local? malloc
'd?), it seems unlikely in the extreme to me that the array of pointers would be shallowly copied to the new process
To address your exact question, this means that almost any source of a null-terminated char*
(including an std::string
, via str.c_str()
or str.data()
) can be used as part of the array passed to execv
. It's worth noting that, pre C++11, std::strings
were not required to be null-terminated, so long as the c_str
member returns a pointer to a null-terminated string. I don't know of any implementation of std::string
which isn't null-terminated, though it's worth noting that, unlike c-strings std::string
s may contain \0
characters as part of the string data, and not as a terminator.
As a side note, the execv
call will instantly replace the calling process with the new one. This means that C++ destructors will not be called. In the case of std::string
, std::vector
, and any other dynamic memory, this doesn't matter- all allocated memory is automatically reclaimed, so nothing will leak. However, other side effects won't occur, either- std::fstream
s won't close their files, etc. Generally this won't ever matter, because destructors with heavy side-effects are poor design practice, but it's something to be aware of.
The strings are copied into the newly-created memory space. So long as they're valid when you call exec
, you don't have to worry.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With