2013-09-19 3 views
0

Я реализовал общий быстрый вид, и теперь я хочу принять массив из командной строки. Ниже приведена функция, которая должна копировать указатели символов из массива argv в базу. Я получаю ошибку сегментации. Копия работает нормально, когда я передаю адрес двух целых чисел.Общая копия с использованием указателя void

#include<stdio.h> 

void copy(void *src, void *dest, int size) 
{ 
    char *s, *d; 
    int i; 

    s = src; 
    d = dest; 

    for(i = 0; i < size; i++) 
     d[i] = s[i]; 
} 

int main(int argc, char *argv[]) 
{ 
    void *base; 
    int i = 10; 
    int j = 20; 

    printf("%d, %d\n", i, j); 
    copy(&i, &j, sizeof(int)); 
    printf("%d, %d\n", i, j); 

    copy(argv, base, sizeof(char *)); 

    return 0; 
} 

Выход

10, 20 
10, 10 
Segmentation fault (core dumped) 
+1

'Base' не имеет пространство, выделенное для него ... вы пытаетесь выжать все из ARGV в ничто. Вам нужно «malloc». –

ответ

-1

ARGV не один указатель, его двойной указатель,

вы должны делать так:

base = calloc(1, sizeof(char *)); 
copy(argv[1], base, sizeof(char *)); 

, если вы действительно хотите скопируйте полный argv, вы должны заменить sizeof (char *) на strlen (argv [0]) и должны locate base с длиной argv [0].

+1

с использованием 'strlen (argv [0])' будет эффективно вызывать имя вашей программы, а не следующие аргументы (от argv [1] до argv [argc-1]). –

+0

Вы правы, я был неправ! спасибо за обнаружение этого – John

1

Вы пытаетесь копировать sizeof(char*) байт в, на что указывает base. Но вы не выделяли никакой памяти base, поэтому программа вызывает неопределенное поведение.

0
void *base = malloc(strlen(argv[0])+1); 

затем

copy(argv[0], base, strlen(argv[0])+1); 

в конце

free(base); 

sizeof(char*) возвращает размер одного указателя, а не весь путь

Edit:

void *base; 
int i; 

if (argc>0) 
{ 
    base = malloc(argc+1);// we have enough pointers for copying args (+1 to null terminat it) 

    for(i=0; i < argc; i++) 
    { 
     base[i] = malloc(strlen(argv[i])+1); 
     copy(argv[i], base[i], strlen(argv[i])+1); 
    } 
    base[i] = NULL; 
} 

база будет двойной указатель держит все аргументы

вы можете сделать memset(...) и memcopy(...) КСТАТИ

+0

с помощью strlen (argv [0]) эффективно даст вам имя вашей программы, а не следующие аргументы (от argv [1] до argv [argc-1]). –

+0

вы просто хотите сжать всех, плюс он хочет протестировать функцию копирования, которую он сделал. argv [0] имеет указатель на строку с именем приложения. Я не заботился о вашем предположении -> «argv [1] для argv [argc-1]» – aah134

+1

«Я хочу принять массив из командной строки». «... должен копировать ** указатели символов ** из array argv to base ". Он уже протестировал свою функцию 'copy' с помощью int swapping (и также тривиально проверить ее правильность). «вы просто хотите сжать всех»: вы знаете, что нисходящий ответ на ответ стоит репутации, не так ли? Ваш ответ и ответ Джона неверны относительно ОП. Отредактируйте, чтобы исправить или уточнить ваш ответ, и я удалю downvote. Во всех действиях я даю upvotes более свободно, чем я даю downvotes: p (отношение составляет около 1: 4 downvotes для upvotes) –

2

argv является массив указателей. Если вы просто хотите, чтобы скопировать указатели вы можете сделать это так:

base = calloc(argc, sizeof(char *)); 
copy(argv, base, argc * sizeof(char *)); 

Теперь у вас есть копия массива указателей argv, но по-прежнему содержит указатели на исходные аргументы argv[i]. Если вы хотите создать копии argv[i] тоже не используют copy() но:

char **base = calloc(argc, sizeof(char *)); 
int i; 

for(i=0; i<argc; i++) 
    base[i] = strdup(argv[i]); 

Но помните: argv[0] этого название программы, и я уверен, вы не хотите, чтобы быть частью массива. Чтобы избежать этого:

base = calloc(argc-1, sizeof(char *)); 
copy(argv+1, base, (argc-1) * sizeof(char *)); 

или

char **base = calloc(argc, sizeof(char *)); 
int i; 

for(i=1; i<argc; i++) 
    base[i-1] = strdup(argv[i]); 
Смежные вопросы