释放内存时堆损坏
Heap corruption while freeing memory
我正在为这段代码苦苦挣扎。顾名思义,函数应该 return 字符串数组,表示作为参数给定的字符串的所有旋转。
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] = '[=10=]';
}
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
,你没有分配 space 的 nul
终止符,所以你应该像这样分配 space
char *double_data = malloc(2 * len + 1));
for
循环中的分配也是如此,即
all_rotations[i] = (char*)malloc(sizeof(char)* len);
当然,解决方法是
all_rotations[i] = malloc(1 + len);
你从不检查是否 malloc()
returns 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] = '[=14=]';
for (index = 0 ; index < length ; index++)
{
memcpy(all_rotations[index], double_data + index, length);
all_rotations[index][length] = '[=14=]';
}
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] != '[=14=]' ; i++)
{
printf("%s\n", asdf[i]);
free(asdf[i]);
}
free(asdf);
}
return 0;
}
我正在为这段代码苦苦挣扎。顾名思义,函数应该 return 字符串数组,表示作为参数给定的字符串的所有旋转。
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] = '[=10=]';
}
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
,你没有分配 space 的nul
终止符,所以你应该像这样分配 spacechar *double_data = malloc(2 * len + 1));
for
循环中的分配也是如此,即all_rotations[i] = (char*)malloc(sizeof(char)* len);
当然,解决方法是
all_rotations[i] = malloc(1 + len);
你从不检查是否
malloc()
returnsNULL
,这是不好的做法。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] = '[=14=]';
for (index = 0 ; index < length ; index++)
{
memcpy(all_rotations[index], double_data + index, length);
all_rotations[index][length] = '[=14=]';
}
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] != '[=14=]' ; i++)
{
printf("%s\n", asdf[i]);
free(asdf[i]);
}
free(asdf);
}
return 0;
}