繁体   English   中英

释放内存时堆损坏

[英]Heap corruption while freeing memory

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

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);

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

您的代码存在一些问题

  1. 当你使用

    strcpy(double_data + len, data);

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

    char *double_data = malloc(2 * len + 1));
  2. for循环中的分配也是如此,即

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

    当然,修复方法是

    all_rotations[i] = malloc(1 + len);
  3. 您永远不会检查malloc()返回NULL ,这是不好的做法。

  4. 不要强制转换 malloc() 的返回值

  5. 不要使用strlen()作为循环的条件,除非字符串的长度在循环内发生变化,因为strlen()在每次调用时计算字符串的长度,因此您正在制作 O(n) 算法 O(n 2 )。

  6. 该标准要求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;
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM