2015-06-14 3 views
4

Ниже представлена ​​программа на языке C, которую я написал для печати различной комбинации символов в строке.бесплатно вызывает разные результаты от malloc

Это не эффективный способ, так как этот алгоритм создает много дополнительных строк. Однако мой вопрос НЕ о том, как решить эту проблему более эффективно.

Программа работает (хотя и неэффективно) и печатает различную комбинацию символов строки (правильно). Но когда я пытаюсь создать free дополнительные строки, которые создаются, я сталкиваюсь с проблемой. free, вызывающий проблему, находится в конце thr recur_printc функция (прокомментировано).

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 

#define N 3 

void recur_printc(char *, int, char *); 
int main() 
{ 
    char str[] = "abc"; 
    char *print_arr = malloc(N * sizeof(char)); 
    //Call recur_print 
    recur_printc(print_arr, 0, str); 
    free(print_arr); 
    return 0; 
} 

void recur_printc(char *print_arr, int index, char *remaining) 
{ 
    int i, j, rem_len, index_4_next; 
    //base case, only last cahracter remaining 
    if(strlen(remaining) == 1) 
    { 
     print_arr[index] = remaining[0]; 
     //Print the print_arr 
     for(i=0; i<N; i++) 
     { 
      printf("%c",print_arr[i]); 
     } 
     printf("\n"); 
     return; 
    } 
    //If more than one character remaining 
    else 
    { 
     rem_len = strlen(remaining); 
     for(i=0; i<rem_len; i++) 
     { 
      //Add one character to print_arr 
      print_arr[index] = remaining[i]; 
      //now create the string with remaining characters 
      char *remaining_for_next = malloc((rem_len-1) * sizeof(char)); 
      index_4_next = 0; 
      for(j=0; j<rem_len; j++) 
      { 
       if(j != i) 
       { 
        remaining_for_next[index_4_next] = remaining[j]; 
        index_4_next++; 
       } 
      } 
      //call recur_print 
      recur_printc(print_arr, index+1, remaining_for_next); 
      //Free the remainin_for_next 
      /*------This is causing issues----*/ 
      //free(remaining_for_next); 
      remaining_for_next = NULL; 
     } 
    } 
} 

Когда я запустил эту программу в gdb я заметил, что когда i=1 для первого экземпляра recur_print, странная вещь происходит с malloc.

Когда эта линия выполнена:

char *remaining_for_next = malloc((rem_len-1) * sizeof(char)); 

Хотя rem_len-1 равна 2, таНос выделяет 3 байт, а затем весь алгоритм не удается, то потому что где-то в коде strlen этой строки используется (который будет 3 вместо 2). . Не уверен, что происходит (. Это не происходит, когда я закомментируйте free() линия)

Ниже выводится GDB:

42    char *remaining_for_next = malloc((rem_len-1) * sizeof(char)); 
(gdb) print remaining_for_next 
$3 = 0x0 
(gdb) n 
43    index_4_next = 0; 
(gdb) print remaining_for_next 
$4 = 0x602030 "@ `" 
(gdb) print rem_len-1 
$5 = 2 
(gdb) q 

Извините за длинный пост. Еще раз, мой вопрос НЕ о том, как печатать comibnation другим (и лучшим) способом. Мой вопрос в том, почему приведенный выше код не работает, когда я пытаюсь освободить строку remaining_for_next (возможно, почему malloc получает влияние).

+0

«* Свободно, что вызывает проблему ... *", если обработка динамически распределенной памяти вызывает проблемы, вы можете обратиться к использованию инструмента проверки памяти, такого как Valgind (https://valgrind.org). – alk

ответ

1

Каждый раз, когда вы создаете свою строку, вы не добавляете нулевой ограничитель, что вызывает ошибку.

Так это изменить:

for(j=0; j<rem_len; j++) { 
    if(j != i) { 
    remaining_for_next[index_4_next] = remaining[j]; 
    index_4_next++; 
    } 
} 

к этому:

for(j=0; j<rem_len; j++) { 
    if(j != i) { 
    remaining_for_next[index_4_next] = remaining[j]; 
    index_4_next++; 
    } 
} 
remaining_for_next[index_4_next] = '\0'; 

Выход:

[email protected]:~/Desktop/px$ gcc -Wall main.c 
[email protected]:~/Desktop/px$ ./a.out 
abc 
acb 
bac 
bca 
cab 
cba 

Совет: Это почти всегда необходимо обнулить аннулирует ваши строки , не забудь!


Важно редактировать:

Как алк заметили, что вам нужно изменить:

char *remaining_for_next = malloc((rem_len - 1) * sizeof(char)); 

к этому:

char *remaining_for_next = malloc((rem_len) * sizeof(char)); 

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


Хороший вопрос, +1.

+0

Это '0'- или' NUL'- или нулевой или нулевой терминатор. Но 'NULL' - это что-то другое. – alk

+0

@alk правильный. Отредактировано, все в порядке? – gsamaras

+1

Я бы сказал, что код по-прежнему не хватает, чтобы выделить место для '0'-терминатора. – alk

2

Я не прошел через все с помощью тонкой зубчатой ​​гребенки, но я верю, что строка remaining_for_next не будет иметь нулевого символа. Вы используете strlen(), который не включает нулевой символ в длину строки, а затем копирует строку, как если бы это был массив символов. Это может быть место для начала поиска. Я предполагаю, что первый раз, когда recur_printc вызывается от себя, поведение будет не таким, каким вы хотите. Попробуйте вручную добавить нулевой символ в remaining_for_next и посмотреть, устраняет ли это проблему.

Смежные вопросы