我在这段代码中苦苦挣扎。顾名思义,函数应返回字符串数组,该数组表示作为参数给出的字符串的所有旋转。

char **str_all_rotations(const char *data)
{
    int i = 0; /* Loop counter */
    len = strlen(data); /* Len of input */

    /******************/
    /*  malloc memory */

    char **all_rotations = (char**)malloc(sizeof(char*)* len);
    char *double_data = (char*)malloc(len * 2 * sizeof(char));

    for (i = 0; i < len; i++)
    {
         all_rotations[i] = (char*)malloc(sizeof(char)* len);
    }

    /*******************/
    /*  Rotations part */

    strcpy(double_data, data);
    strcpy(double_data + len, data);

    for (i = 0; i < len; i++)
    {
        strncpy(all_rotations[i], double_data + i, len);
        all_rotations[i][len] = '\0';
    }

    free(double_data); /* Release memory */

    return all_rotations;
}


从算法的角度来看,它工作正常,但是只需简单调用此函数

char *str = "omgillsetyouonfire";
char **asdf = str_all_rotations(str);

for (int i = 0; i < strlen(str); i++)
{
    free(asdf[i]);
}

free(asdf);


失败,因为堆损坏。我看不出有什么问题。
如何甚至调试这种错误?

最佳答案

您的代码有一些问题


使用时

strcpy(double_data + len, data);


您将一个额外的字节复制到您没有为其分配空间的double_data终止符nul,因此您应该像这样分配空间

char *double_data = malloc(2 * len + 1));

for循环中的分配也是如此,即

all_rotations[i] = (char*)malloc(sizeof(char)* len);


当然解决办法是

all_rotations[i] = malloc(1 + len);

您永远不会检查malloc()是否返回NULL,这是一种不好的做法。
Do not cast the return value of malloc()
除非在循环内字符串的长度发生变化,否则请勿将strlen()用作循环的条件,因为strlen()在每次调用时都会计算字符串的长度,因此您要使用O(n)算法O(n2 )。
该标准要求sizeof(char) == 1,因此只会使您的代码混乱。


这是您自己的代码,已解决上述问题

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

char **
str_all_rotations(const char *const data)
 {
    int    index;
    char **all_rotations;
    char  *double_data;
    int    length;

    if (data == NULL)
        return NULL;
    length        = strlen(data);
    index         = 0;
    all_rotations = malloc(length * sizeof(*all_rotations));
    if (all_rotations == NULL)
        return NULL;
    double_data = malloc(2 * length + 1);
    if (double_data == NULL)
        goto cleanup;
    for (index = 0 ; index < length ; index++)
     {
        all_rotations[index] = malloc(1 + length);
        if (all_rotations[index] != NULL && index < 4)
            continue;
        goto cleanup;
     }
    memcpy(double_data, data, length);
    memcpy(double_data + length, data, length);

    double_data[2 * length] = '\0';
    for (index = 0 ; index < length ; index++)
     {
        memcpy(all_rotations[index], double_data + index, length);
        all_rotations[index][length] = '\0';
     }
    free(double_data);

    return all_rotations;

cleanup:
    while (index >= 0)
        free(all_rotations[index--]);
    free(all_rotations);
    free(double_data);

    return NULL;
 }

int
main(void)
 {
    char  *str  = "omgillsetyouonfire";
    char **asdf = str_all_rotations(str);

    if (asdf != NULL)
     {
        for (int i = 0 ; str[i] != '\0' ; i++)
         {
            printf("%s\n", asdf[i]);
            free(asdf[i]);
         }
        free(asdf);
     }

    return 0;
 }

关于c - 堆损坏,同时释放内存,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30557265/

10-10 13:20