Вам нужно использовать strcpy()
, чтобы скопировать argv[optind]
в ваше *tempPaths
пространство, которое вы только что выделили.
Как таковое, вы затираете (вытекаете) выделенную память, а затем ктознает, что еще идет не так.
Кроме того, зачем вам нужно копировать свои аргументы?Если вы не изменяете их, вам не нужно их копировать.
char **tempPaths = paths;
while (optind < argc)
{
printf("test1\n");
// Or use strdup(), but strdup() is POSIX, not Standard C
// This wastes less space on short names and works correctly on long names.
*tempPaths = malloc(strlen(argv[optind])+1);
// Error check omitted!
strcpy(*tempPaths, argv[optind]);
printf("test2\n");
printf("%s\n", *tempPaths);
tempPaths++;
optind++;
}
Предполагается, что вам необходимо скопировать аргументы.Если вам не нужно изменять аргументы командной строки, вы можете просто использовать:
char **tempPaths = paths;
while (optind < argc)
*tempPaths++ = argv[optind++];
Код, который там был, просто исчез, когда я редактировал, чтобы удалить то, что больше не нужно ...
Возможно даже установить просто:
char **paths = &argv[optind];
Это полностью устраняет цикл и временные переменные!
Отвечая на вопросы в комментарии
[W] Что вы имеете в виду, когда говорите, что моя выделенная память протекает?
Ваш оригинальный код:
*tempPaths = malloc(BUFSIZ);
*tempPaths = argv[optind];
Первый оператор выделяет память для *tempPaths;второй затем перезаписывает (единственная ссылка) этот указатель указателем argv [optind], тем самым гарантируя, что вы не можете освободить выделенную память, а также гарантируя, что вы его не используете.Кроме того, если вы впоследствии попытаетесь освободить память, на которую указывает ... ну, на этом этапе это будет paths
, а не tempPaths
... тогда вы пытаетесь освободить память, которая никогда не выделялась, что такжеПлохая вещь ™.
Также я не совсем понимаю, что вы имеете в виду под «копированием своих аргументов».Вы имеете в виду две директории, используемые для командной строки или для чего-то еще?
Ваш код создает копию аргументов (имен каталогов), передаваемых программе;пересмотренное решение, использующее strdup()
(или примерно то же самое, что и strdup()
), создает копию данных в argv[optind]
.Однако, если все, что вы собираетесь делать с данными, - это прочитать их без изменения, вы можете просто скопировать указатель, а не делать копию данных.(Даже если бы вы собирались изменить аргумент, если бы вы были осторожны, вы все равно могли бы использовать исходные данные - но тогда сделать копию безопаснее.)
Наконец-то не будет char ** paths = & argv [optind];просто дай мне один каталог и все?
Нет;он даст вам указатель на список указателей на строки с нулевым символом в конце, который вы можете просмотреть:
for (i = 0; paths[i] != 0; i++)
printf("name[%d] = %s\n", i, paths[i]);
Голый минимальный рабочий код
Как отмечено в комментарииосновная проблема с расширенным кодом сбоя (за исключением того факта, что у нас нет заголовка) состоит в том, что переменная paths
не инициализируется, чтобы указывать на что-либо.Неудивительно, что после этого происходит сбой кода.
На основе исправленного примера - с удалением обработки опций:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char **paths;
optind = 1;
paths = &argv[optind];
if (argc - optind + 1 < 3)
{
fprintf(stderr, "Usage: %s dir1 dir2 [dirn ... ]\n", argv[0]);
exit(EXIT_FAILURE);
}
else
{
char **tmp = paths;
while (*tmp != 0)
printf("<<%s>>\n", *tmp++);
}
return 0;
}
И эта версия выделяет память:
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
optind = 1;
if (argc - optind + 1 < 3)
{
fprintf(stderr, "Usage: %s dir1 dir2 [dirn ... ]\n", argv[0]);
exit(EXIT_FAILURE);
}
else
{
int npaths = argc - optind;
char **paths = malloc(npaths * sizeof(*paths));
// Check allocation!
char **tmp = paths;
int i;
printf("n = %d\n", npaths);
for (i = optind; i < argc; i++)
{
*tmp = malloc(strlen(argv[i])+1);
// Check allocation!
strcpy(*tmp, argv[i]);
tmp++;
}
for (i = 0; i < npaths; i++)
printf("<<%s>>\n", paths[i]);
}
return 0;
}