2015-06-14 53 views
4

下面是我写的一个C程序,用于打印字符串中不同字符的组合。free from 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=1recur_print第一个实例,一个奇怪的事情发生与malloc

当执行该行:

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

虽然rem_len-1等于2,malloc的分配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 

很抱歉的长期职位。再次,我的问题不是关于如何以不同(更好)的方式打印联合。我的问题是,当我尝试释放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 

提示:它几乎总是一个必须为null终止您的字符串, 别忘记了!


重要编辑:

由于ALK注意到了,你需要这个改变:为了腾出空间为

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

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

本空终止符。


不错的问题+1。

+0

它是'0'或'NUL'或零或终止符。但是'NULL'是不同的。 – alk

+0

@alk正确。编辑,现在好吗? – gsamaras

+1

我想说代码仍然错过了为'0'结束符分配空间。 – alk

2

我还没有通过一个精细的齿梳,但我相信remaining_for_next字符串将不会有空字符终止。您正在使用strlen(),它不包含字符串长度中的空字符,然后将该字符串复制为一个字符数组。它可能是一个开始搜索的地方。我会想象第一次从自己调用recur_printc时,行为将不会是你想要的。尝试手动将空字符追加到remaining_for_next并查看是否可以解决问题。