2015-11-08 1 views
0

Поэтому я хочу, чтобы моя программа могла сохранять несколько (или в этом случае только два) аргумента в строку, если программа запущена с опцией -a , Вот код:Ошибка «invalid pointer» с realloc и strcat, работающими на argv

#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <string.h> 
#include <unistd.h> 
#include <getopt.h> 

int main(int argc, char **argv) { 

char c; 
char *optstr; 
int acount = 0; 

    while((c = getopt(argc, argv, "a")) != -1) { 

     switch(c) { 
      case 'a': acount++; break; 
      case '?': fprintf(stderr, "wrong opt\n"); exit(1); break; 
      default: assert(0); 
     } 
    } 
    char *temp; 
    if(acount == 1) { 
     optstr = argv[optind]; 
     temp = strdup(optstr); 
     if(optind+1 < argc) { 
      temp = realloc(temp, (strlen(temp) + 1 + sizeof(" "))); 
      temp = strcat(temp, " "); 
      temp = realloc(temp, (strlen(temp) + 1 + strlen(argv[optind+1]))); 
      temp = strcat(temp, argv[optind+1]); 
     } 
    } else { 
     fprintf(stderr, "too many or not enough a's\n"); 
     exit(1); 
    } 

    fprintf(stdout, "%s\n", temp); 
return 0; 

} 

Мой вопрос заключается в том, что весь бизнес realloc продолжается. Я изначально пробовал все это без переменной temp, и вместо этого использовал optstr. Это только дало мне ошибки «realloc(): invalid pointer». Я спрашиваю: почему, и почему это внезапно работает с temp? Это потому, что указатель optstr указывает на аргумент в argv, а изменение argv вызывает ошибки? Я совсем не уверен.

+0

Какова ценность 'argv [optind]', когда вы его используете? –

+2

'sizeof (" ")'? Вы имели в виду 'strlen (" ")'? Кстати, вы не освободили выделенную память. –

+0

В этом случае это имеет значение? Он работает нормально. И да, я знаю, что не освободил свою память, но это всего лишь пример. – skulpt

ответ

0

Это потому, что вы не знаете, как выделяется память для строк внутри argv. Вы не должны знать. Они могли быть созданы индивидуально с использованием malloc, и в этом случае realloc будет работать (но это не является законным), или большой блок был malloc 'd и строки, помещенные внутри блока, и в этом случае он не будет работать, или какой-либо другой варианты.

Когда вы вызываете realloc на указатель от argv, вы утверждаете, что владеете этой памятью; это неверно, и вам не разрешается перераспределять или освобождать его. См. Также Memory allocation and **argv argument

Вы можете читать только память, так что вы можете сделать и сделали, это использовать strdup для создания копии; в этой памяти вы тогда do own, так что теперь вам разрешено использовать realloc.