C语言 为什么会发生堆损坏?



我一直在为学校做一些练习题,在其中一个题中,输入的整数必须写入动态分配的字符串。代码可以正常工作,直到它释放分配的内存,堆损坏发生。

有人可以解释为什么会发生这种情况以及我做错了什么吗?

int main() {
char *string = NULL;
char **string2 = &string;
Conversion(string2);
printf("Entered number converted to string: %s", string);
free(string);
return 0;
}
int Conversion(char **string) {
int num = 0, temp = 0, dcount = 0;
printf("Enter number: ");
scanf(" %d", &num);
temp = num;
while (temp != 0) {
temp /= 10;
dcount++;
}
*string = (char*)malloc(dcount*sizeof(char));
if (*string == NULL) {
printf("Error during memory allocation!");
return -1;
}
sprintf(*string, "%d", num);
return 0;
}

您需要分配一个额外的字符来考虑终止符。

*string = (char*)malloc((dcount + 1) * sizeof(char));

此外,如果num为 0 或负数,则dcount不正确。

其他评论:

  • 可以使用snprintf()来计算所需的缓冲区大小。它将为您节省所有繁重的工作 计算num中的数字 ,而且它将正确处理所有边缘情况。

    int dcount = snprintf(NULL, 0, "%d", num);
    
  • 应避免强制转换 malloc 的返回值。

    *string = malloc((dcount + 1) * sizeof(char));
    
  • sizeof(char)定义为 1。我会省略乘法

    *string = malloc(dcount + 1);
    

    但是,如果保留它,请避免对项目类型进行硬编码。

    *string = malloc((dcount + 1) * sizeof(**string));
    

    如果您将字符串从char*更改为char16_t*/char32_t*/wchar_t*,这会自动调整,而sizeof(char)尽管类型不匹配,但编译时不会出错。

该函数有几个缺点。

对于初学者,您不考虑已分配字符串的终止零''

其次,用户可以输入0作为数字。在这种情况下,dcount的值将不正确,因为循环

while (temp != 0) {
temp /= 10;
dcount++;
}

将被跳过。

第三,该函数将无法正确处理负数,允许用户输入负数。

本声明

char **string2 = &string;

是多余的。您可以通过以下方式调用该函数

Conversion( &string );

它不是应该要求用户输入数字的函数。该函数应该只执行一项任务:将整数转换为字符串。

还有一个功能设计缺点。

从函数声明

int Conversion(char **string); 

(这应该在函数之前main) 不清楚用户是否应该为字符串提供内存,或者它是为字符串分配内存的函数。

该函数的更好界面如下所示,如下面的演示程序所示。

#include <stdio.h>
#include <stdlib.h>
char * Conversion( int x )
{
const int Base = 10;
size_t digits = x < 0 ? 1 : 0;
int tmp = x;
do
{
++digits;
} while ( tmp /= Base );
char *s = malloc( digits + sizeof( ( char )'' ) );
if ( s != NULL ) sprintf( s, "%d", x );
return s;
}
int main( void )
{
int num = 0;
printf( "Enter a number: " );
scanf( "%d", &num );
char *s = Conversion( num );
if ( s != NULL )
{
printf( "The entered number converted to string: %sn", s );
}
else
{
puts( "A conversion error ocured." );
}
free( s );
}

其输出可能如下所示

Enter a number: -12
The entered number converted to string: -12

考虑到根据 C 标准,没有参数的函数main应声明为

int main( void )

相关内容

  • 没有找到相关文章