передача целочисленных аргументов при использовании execve - PullRequest
1 голос
/ 10 августа 2010

Я новичок в программировании с использованием системных вызовов в C. Я пытаюсь использовать вызов execve в одной из моих программ. Я должен передать целое число в качестве аргумента программе, которая вызывается через execve. Однако, читая в Интернете и видя пример кода, я вижу, что мы можем передавать только строки в качестве аргументов. Итак, я попытался преобразовать целое число в строку, используя sprintf, а затем используя strcpy, чтобы скопировать эту строку в один из элементов массива строк, который должен быть передан через execve. Но использование strcpy приводит к ошибке сегментации. Я проверил это путем отладки, и если я не использую strcpy, а просто напишу что-то вроде - myargv [1] = "123"; тогда вся программа работает нормально. Но так как мне нужно передать переменное целое число в качестве параметра, а не константу, я не могу использовать вышеуказанный метод.

Эта проблема беспокоила меня в течение некоторого времени. Пожалуйста, помогите мне с тем, что я должен делать.

Ответы [ 2 ]

4 голосов
/ 10 августа 2010

Это почти наверняка, потому что вы не выделили место для вашей строки.

Причина, по которой myargv[1]="123"; работает, заключается в том, что вы устанавливаете указатель на указатель на строку, которая уже существует (компилятор обычно помещает это "123 "в предварительно инициализированную память, и это только загружается).Используя что-то вроде:

char *myargv[10];
strcpy (myargv[1], "anything");

, вы обычно сталкиваетесь с проблемами, потому что для указателя myargv[1] не выделено резервное хранилище.


Вы можете простоустановить myargv[1] непосредственно в буфер, в котором вы sprintf -недренировали строку:

char sprintf_buffer[whatever];
sprintf (sprintf_buffer, "%d", myInteger);
myargv[1] = sprintf_buffer;

Или, если вы повторно используете этот буфер (чтобы значение перезаписывалось для нескольких целочисленных аргументов), используйте strdup.

char sprintf_buffer[whatever];
sprintf (sprintf_buffer, "%d", myInteger1);
myargv[1] = strdup (sprintf_buffer);
sprintf (sprintf_buffer, "%d", myInteger2);
myargv[2] = strdup (sprintf_buffer);

И если по какой-то причине у вашей платформы нет a strdup, вот один для вас:

char *strdup (const char *s) {
    char *d = (char *)(malloc (strlen (s) + 1));
    if (d != NULL)
        strcpy (d,s);
    return d;
}

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


Вы можете избежать выделения памяти с помощью нескольких буферов (при условии, что вы заранее знаете абсолютное количество буферов):

char sprintf_buffer1[whatever];
char sprintf_buffer2[whatever];
sprintf (sprintf_buffer1, "%d", myInteger1);
myargv[1] = sprintf_buffer1;
sprintf (sprintf_buffer2, "%d", myInteger2);
myargv[2] = sprintf_buffer2;
0 голосов
/ 10 августа 2010

Мне неясно, почему вы вообще используете strcpy.Просто snprintf число в строке и укажите один из аргументов.

например

char numberArgBuffer[20];    // more than big enough for a 32 bit integer
snprintf(numberArgBuffer, 20, "%d", numberArg);
char* argv[3];
char* envp[1];
argv[0] = exeName;           // could be same as path
argv[1] = numberArgBuffer;
argv[2] = NULL;
envp[0] = NULL;
int ret = execve(path, argv, envp);
// if you get here execve failed, so handle the error

Ваш strcpy, вероятно, является ошибкой сегмента, потому что вы не выделили буферпункт назначения, но, как показывает приведенный выше пример, в любом случае это ненужный шаг.

...