C 为什么会发生堆损坏?
我一直在为学校做一些练习题,在其中一个练习题中,输入的整数必须写入一个动态分配的字符串。在释放分配的内存之前,代码可以很好地完成它的工作,而此时会发生堆损坏 有人能解释一下为什么会这样,我做错了什么吗C 为什么会发生堆损坏?,c,string,pointers,segmentation-fault,dynamic-memory-allocation,C,String,Pointers,Segmentation Fault,Dynamic Memory Allocation,我一直在为学校做一些练习题,在其中一个练习题中,输入的整数必须写入一个动态分配的字符串。在释放分配的内存之前,代码可以很好地完成它的工作,而此时会发生堆损坏 有人能解释一下为什么会这样,我做错了什么吗 int main() { char *string = NULL; char **string2 = &string; Conversion(string2); printf("Entered number converted to string: %s", strin
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;
}
您需要为
\0
终止符分配一个额外字符
*string = (char*)malloc((dcount + 1) * sizeof(char));
如果num
为0或负值,则dcount
也不正确
其他意见:
- 你可以。它将为您节省在
中计算数字的所有繁重工作,并且它将正确处理所有边缘情况num
int dcount = snprintf(NULL, 0, "%d", num);
- 你应该
定义为1。我会省略乘法运算sizeof(char)
然而,如果你真的离开了它 如果将字符串从*string = malloc(dcount + 1);
更改为char*
/char16\u t*
/char32\u t*
这将自动调整,而wchar\u t*
尽管类型不匹配,但编译时不会出错sizeof(char)
\0
终止符分配一个额外字符
*string = (char*)malloc((dcount + 1) * sizeof(char));
如果num
为0或负值,则dcount
也不正确
其他意见:
- 你可以。它将为您节省在
中计算数字的所有繁重工作,并且它将正确处理所有边缘情况num
int dcount = snprintf(NULL, 0, "%d", num);
- 你应该
定义为1。我会省略乘法运算sizeof(char)
然而,如果你真的离开了它 如果将字符串从*string = malloc(dcount + 1);
更改为char*
/char16\u t*
/char32\u t*
这将自动调整,而wchar\u t*
尽管类型不匹配,但编译时不会出错sizeof(char)
'\0'
其次,用户可以输入0
作为数字。在这种情况下,dcount
的值将不正确,因为循环
while (temp != 0) {
temp /= 10;
dcount++;
}
将跳过
第三,该函数无法正确处理负数,允许用户输入负数
本声明
char **string2 = &string;
int Conversion(char **string);
这是多余的。您可以按以下方式调用该函数
Conversion( &string );
Enter a number: -12
The entered number converted to string: -12
它不是要求用户输入数字的函数。该函数只应执行一项任务:将整数转换为字符串
还有一个功能设计缺陷
从函数声明中
char **string2 = &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 )'\0' ) );
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: %s\n", s );
}
else
{
puts( "A conversion error ocured." );
}
free( s );
}
考虑到根据C标准,不带参数的功能main
应声明如下
int main( void )
该功能有几个缺点 对于初学者,您不考虑所分配字符串的终止零
'\0'
其次,用户可以输入0
作为数字。在这种情况下,dcount
的值将不正确,因为循环
while (temp != 0) {
temp /= 10;
dcount++;
}
将跳过
第三,该函数无法正确处理负数,允许用户输入负数
本声明
char **string2 = &string;
int Conversion(char **string);
这是多余的。您可以按以下方式调用该函数
Conversion( &string );
Enter a number: -12
The entered number converted to string: -12
它不是要求用户输入数字的函数。该函数只应执行一项任务:将整数转换为字符串
还有一个功能设计缺陷
从函数声明中
char **string2 = &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 )'\0' ) );
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: %s\n", s );
}
else
{
puts( "A conversion error ocured." );
}
free( s );
}
考虑到根据C标准,不带参数的功能main
应声明如下
int main( void )
啊!我知道这将是一件愚蠢的显而易见的事情,就像往常一样。谢谢你的时间,特别是所有额外的评论。snprintf()将在将来非常有用。这也是一篇关于malloc转换的有趣文章,因为我们在课堂上被告知,我们需要自己转换它,因为它返回一个空指针。Doh!我知道这将是一件愚蠢的显而易见的事情,就像往常一样。谢谢你的时间,特别是所有额外的评论。snprintf()将在将来非常有用。这也是一篇关于malloc强制转换的有趣阅读,因为我们在课堂上被告知,我们需要自己强制转换它,因为它返回一个空指针。这只是一段代码片段,其中包含了表示我遇到的问题所需的部分:)我在自定义头中声明AI使用的所有内容。但是谢谢你的回答。在你的和上面的一个之间,我学到了很多,比我从我的问题中得到的要多得多!这只是一段代码片段,其中包含表示我遇到的问题所需的部分:)我在自定义头中声明AI使用的所有内容。但是谢谢你的回答。在你的和上面的一个之间,我学到了很多,比我从我的问题中得到的要多得多!错误:1)子函数:
Conversion()
缺少原型,因此编译器将假定参数的类型和返回的类型可能正确(也可能不正确)。2) 实际子函数返回一个“int”,表示调用malloc()
失败/成功,但main()
中的调用在mal>时无法检查返回的值