free 导致 malloc 产生不同的结果

free causing different results from malloc

下面是我编写的用于打印字符串中不同字符组合的 C 程序。

这不是一种有效的方法,因为该算法会创建大量额外的字符串。但是我的问题不是关于如何更有效地解决这个问题。

该程序工作(虽然效率低下)并打印字符串字符的不同组合(正确)。但是,当我尝试 free 正在创建的额外字符串时,我 运行 出现了问题。导致问题的 free 位于 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 character 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 的第一个实例时,一个 st运行ge 事情发生了与 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
 = 0x0
(gdb) n
43              index_4_next = 0;
(gdb) print remaining_for_next
 = 0x602030 "@ `"
(gdb) print rem_len-1
 = 2
(gdb) q

抱歉这么久 post。再一次,我的问题不是关于如何以不同(和更好)的方式打印组合。我的问题是为什么当我尝试释放 remaining_for_next 字符串时上面的代码失败(也许是 malloc 受到影响的原因)。

我还没有仔细梳理过所有内容,但我相信 remaining_for_next 字符串不会有空字符终止。您使用的 strlen() 不包含字符串长度中的空字符,然后将字符串复制为字符数组。它可能是开始搜索的地方。我想第一次从自身调用 recur_printc 时,行为不会是你想要的。尝试手动将空字符附加到 remaining_for_next,看看是否能解决问题。

每次创建字符串时,您都没有附加空终止符,这会导致错误。

所以改变这个:

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] = '[=11=]';

输出:

gsamaras@gsamaras:~/Desktop/px$ gcc -Wall main.c
gsamaras@gsamaras:~/Desktop/px$ ./a.out 
abc
acb
bac
bca
cab
cba

提示:几乎总是必须以空终止字符串,不要忘记它!


重要编辑:

正如 alk 所注意到的,您需要对此进行更改:

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

对此:

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

为了使space成为空终止符。


好问题,+1。