execv () и постоянство - PullRequest
       26

execv () и постоянство

28 голосов
/ 10 октября 2008

Я часто использую функцию execv () в C ++, но если некоторые аргументы находятся в строках C ++. Меня раздражает, что я не могу этого сделать:

const char *args[4];

args[0] = "/usr/bin/whatever";
args[1] = filename.c_str();
args[2] = someparameter.c_str();
args[3] = 0;

execv(args[0], args);

Это не компилируется, потому что execv () принимает char * const argv [] , который не совместим с const char *, поэтому я должен скопировать мои std :: strings в символьные массивы с помощью strdup () что боль.

Кто-нибудь знает причину этого?

Ответы [ 4 ]

32 голосов
/ 10 октября 2008

Базовые спецификации Open Group объясняют, почему это так: для совместимости с существующим C-кодом. Однако ни указатели, ни содержимое строк сами по себе не предназначены для изменения. Таким образом, в этом случае вы можете сойти с const_cast -ing результатом c_str().

Цитата:

Утверждение о том, что argv[] и envp[] являются константами, включено для того, чтобы дать будущим авторам языковых связей явное указание на то, что эти объекты полностью постоянны. Из-за ограничения стандарта ISO C эту идею невозможно изложить в стандарте C. Задание двух уровней const - квалификации для параметров argv[] и envp[] для функций exec может показаться естественный выбор, учитывая, что эти функции не изменяют ни массив указателей, ни символов, на которые указывает функция, но это запретило бы существующий правильный код. Вместо этого только массив указателей помечается как постоянный.

Таблица и текст после этого еще более проницательны. Однако переполнение стека не позволяет вставлять таблицы, поэтому в приведенной выше цитате должно быть достаточно контекста для поиска нужного места в связанном документе.

2 голосов
/ 10 октября 2008

const - вещь C ++ - execv принимает аргументы char * еще до того, как существовал C ++.

Вы можете использовать const_cast вместо копирования, потому что execv фактически не изменяет свои аргументы. Вы можете написать обертку, чтобы сэкономить печатать.

На самом деле, большая проблема с вашим кодом заключается в том, что вы объявили массив символов вместо массива строк.

Try: const char * args [4];

1 голос
/ 08 апреля 2015

Это просто ситуация, когда const в стиле C / C ++ работает не очень хорошо. На самом деле ядро ​​не собирается изменять аргументы, передаваемые exec (). Он просто скопирует их, когда создаст новый процесс. Но система типов не достаточно выразительна, чтобы по-настоящему справиться с этим.

Многие люди на этой странице предлагают сделать exec take "char **" или "const char * const []". Но ни один из них на самом деле не работает для вашего оригинального примера. «char **» означает, что все изменчиво (конечно, это не так для строковой константы «/ usr / bin / what»). «const char * const []» означает, что ничто не является изменяемым. Но тогда вы не можете присвоить какие-либо значения элементам массива, так как сам массив тогда является постоянным.

Лучшее, что вы могли бы сделать, это иметь константу C времени компиляции, такую ​​как:

const char * const args[] = {
  "/usr/bin/whatever",
  filename.c_str(),
  someparameter.c_str(),
  0};

Это на самом деле будет работать с предложенной сигнатурой типа "const char * const []". Но что, если вам нужно переменное количество аргументов? Тогда у вас не может быть постоянной времени компиляции, но вам нужен изменяемый массив. Итак, вы вернулись к обману. Это реальная причина, по которой сигнатура типа exec принимает в качестве аргументов "const char **".

Кстати, проблемы в C ++ такие же. Вы не можете передать std :: vector в функцию, которая нуждается в std :: vector . Вы должны типизировать или скопировать весь std :: vector.

0 голосов
/ 25 марта 2011

Я обычно взламывал это:

#define execve xexecve
#include <...>
#include <...>
#include <...>
#undef execve

// in case of c++
extern "C" {
    int execve(const char * filename, char ** argvs, char * const * envp);
}

/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...