Второй аргумент execve
определен как список строк, заканчивающийся NULL, поэтому вы не можете просто передать адрес path
. Он ожидает массив, подобный этому, с конечной записью NULL:
arg[0] = "/bin/ls"
arg[1] = "-l"
arg[2] = "/usr/include/std*"
arg[3] = NULL
Причина неудачного указателя в том, что execve
смотрел бы на каждое слово, следующее за path
, чтобы найти аргументы, и рассматривал каждое слово как указатель, пока оно не добралось до первого 0 слова. Поскольку path
был один в стеке, он пытался бы интерпретировать любой мусор, который оказался в памяти после стека, превышающего path
, как строковый указатель.
Решение простое: вам нужно создать массив параметров и добавить терминатор NULL (так как он имеет переменную длину). Ниже приведен фиксированный пример (с учетом нескольких предупреждений):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
int main()
{
char* path[] = { "/bin/sh", NULL };
int err = execve(path[0], path, NULL);
printf("%d\n", err);
printf("%s\n", strerror(errno));
printf("%p, %p\n", path, &path);
return 0;
}