Прерывание указателя strcpy char

У меня есть этот код:

     char **arr;
     char* line=NULL;
     int i=0;
     size_t len=0;
     ssize_t read1;

     fp=fopen("list.txt","r");
     if(fp==NULL)
         exit(EXIT_FAILURE);

     while((read1=getline(&line,&len,fp))!=-1)
         i++;
     fclose(fp);

     fp=fopen("list.txt","r");
     if(fp==NULL)
         exit(EXIT_FAILURE);

     arr=(char**)malloc(i*sizeof(char*)); // i is a variable i use to know the number of lines
     i=0;

     while((read1=getline(&line,&len,fp))!=-1)
     {
         line[strlen(line)]='\0';
         arr[i]=(char*)malloc(strlen(line)+1);
         strcpy(arr[i],line);
         i++;
     }

При попытке strcpy программа вылетает. Проблема в malloc? Я очень уверен, что i достаточно большой. И line это char* и сначала NULL.

РЕДАКТИРОВАТЬ: я забыл, что эта программа находится в Qt.


person Emil Grigore    schedule 24.01.2013    source источник
comment
Вам не нужно приводить возвращаемое значение malloc() в программе C.   -  person Carl Norum    schedule 24.01.2013
comment
i — это переменная, которую я использую для определения количества строк. Тогда почему она называется i, а не numberOfLines/linesNumber?   -  person LihO    schedule 24.01.2013
comment
Как определяется line? И каково определение/значение len?   -  person Evan Teran    schedule 24.01.2013
comment
Откуда вы знаете, что начальный i достаточно велик?   -  person Oliver Charlesworth    schedule 24.01.2013
comment
@Oil: действительно, хороший улов, @Emil, каково значение i перед этим кодом?   -  person Evan Teran    schedule 24.01.2013
comment
line[strlen(line)]='\0' ничего не значит.   -  person Theodoros Chatzigiannakis    schedule 24.01.2013
comment
@Emil: поскольку вы определяете line как NULL, это означает, что вы ожидаете, что getline выделит для вас буфер. Итак, пара вещей. 1) Тогда вам не нужен strcpy, вы можете просто сохранить указатель, он ваш. 2) вам нужно установить строку в NULL после того, как вы закончите с ней, в противном случае следующий вызов будет повторно использовать этот буфер, возможно, он будет слишком коротким и переполнится, если это более длинная строка!   -  person Evan Teran    schedule 24.01.2013
comment
@Emil: если ваш код написан на Qt, то это C++, а НЕ c. Это разные языки. И в С++ есть НАМНОГО более простые способы сделать это.   -  person Evan Teran    schedule 24.01.2013
comment
Qt не видно. Ни С++. Обратите внимание, что при использовании правильных типов C++ (и/или Qt) ваша проблема исчезнет.   -  person Frank Osterfeld    schedule 24.01.2013
comment
@EvanTeran Я согласен. С обновленным кодом алгоритм подсчета строк перед фактическим циклом кода протекает как сито (т. Е. Первый цикл while, если getline() действительно выделяет память).   -  person WhozCraig    schedule 24.01.2013
comment
@Emil: Кстати, я только что попробовал ваш код verbatum, и здесь нет сбоя.   -  person Evan Teran    schedule 24.01.2013
comment
@Evan Teran Возможно, вы правы. Когда я запускаю код из консоли в Linux, он работает нормально, но когда я запускаю его из Linux, он вылетает.   -  person Emil Grigore    schedule 24.01.2013
comment
@Emil: вы пытались запустить отладчик, чтобы увидеть, где происходит настоящий сбой?   -  person Evan Teran    schedule 24.01.2013
comment
@Emil Grigore: Когда я пытаюсь использовать strcpy, программа падает. Проблема с malloc? Я очень уверен, что я достаточно большой. Да! вам нужно проверить на NULL   -  person qPCR4vir    schedule 25.01.2013


Ответы (2)


Есть пара проблем с кодом, я прокомментирую то, что, по моему мнению, должно работать...:

 // I **assume** that these are the definitions for these variables 
 // based on your comments
 size_t len = 0;
 char *line = NULL;
 ssize_t read1;

 // I **assume** that i has a reasonable value here, but this is not good to assume, 
 // what if the file is a line longer tomorrow? I hope that you calculate the number 
 // of lines somehow, that would be "less bad"
 int i = 10; // 10 lines in the file, who knows ?!?
 char **arr;

 // don't bother casting...
 arr = malloc(i * sizeof(char*)); 
 i=0;

 while((read1 = getline(&line, &len, fp)) != -1) {

     // THIS LINE DOES NOTHING, so we can just remove it
     // line[strlen(line)]='\0';

     arr[i] = line; // since you asked getline to allocate a buffer for 
                    // you (line was NULL), you can just store the buffer directly
                    // it's YOURS
     i++;

     // THIS IS THE BIG ONE:
     // it is needed because otherwise the NEXT call to getline will 
     // reuse the same buffer, which may not be big enough
     line = NULL;
 }

Кроме того, позже для очистки вы должны сделать что-то вроде этого:

int j;
for(j = 0; j < i; ++j) {
    free(arr[j]);
}
free(arr);
arr = NULL; // not necessary, but good practice to avoid double frees and such
person Evan Teran    schedule 24.01.2013
comment
Спасибо, но это все еще не работает. Я отредактирую код, чтобы он был более понятным. - person Emil Grigore; 24.01.2013
comment
+1: @EmilGrigore, пожалуйста, сделайте, потому что, если getline() делает то, что это предписывает, этот код правильный (за исключением отсутствующей проверки i, которая, безусловно, является худшей именованной переменной в этом блоке кода. - person WhozCraig; 24.01.2013
comment
@ Эмиль, пожалуйста, определите, что это не работает, потому что код, который я предоставил, не должен падать, насколько мне известно. Вы пытались добавить reNULLing строки, как в моем коде? - person Evan Teran; 24.01.2013
comment
@Evan Teran Да, я пытался, но все равно вылетает. - person Emil Grigore; 24.01.2013
comment
@Emil:: также, основываясь на ваших изменениях, вам нужно установить line на NULL перед вторым циклом (тот, который фактически читает строки). Потому что более ранний цикл подсчета установил line в значение, отличное от NULL. - person Evan Teran; 24.01.2013
comment
Я пробовал это, но я все еще получаю сбой - person Emil Grigore; 24.01.2013
comment
@Evan Teran Мне удалось заставить это работать. Казалось, что мне пришлось переключить некоторые настройки qt .... Я никогда раньше не использовал qt. Большое спасибо и извините за беспокойство. - person Emil Grigore; 24.01.2013
comment
строка = НУЛЬ; длина=0; ?? - person qPCR4vir; 24.01.2013
comment
@Evan Teran: причина может быть простой, он не проверяет NULL после malloc ?? - person qPCR4vir; 25.01.2013

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

 arr=(char**)malloc(i_ori*sizeof(char*));//i_ori is a variable i use to know the number of lines
 i=0;

 while((read1=getline(&line,&len,fp))!=-1 && i<i_ori)

Кроме того, вы никогда не проверяете, возвращает ли malloc NULL !! См. https://stackoverflow.com/a/2280342/1458030.

@Emil Grigore: Когда я пытаюсь использовать strcpy, программа падает. Проблема с malloc? Я очень уверен, что я достаточно большой.

Да! вам нужно проверить на NULL.

Если вы используете C++ и Qt, почему бы не использовать контейнеры и потоки?

person qPCR4vir    schedule 24.01.2013
comment
Я уверен, что у меня такое же количество строк, как и у меня. - person Emil Grigore; 24.01.2013
comment
@EmilGrigore: Тогда отредактируйте свой пост, включив в него минимальный тестовый пример, демонстрирующий это. - person Oliver Charlesworth; 24.01.2013