在 c 中使用 malloc 进行操作时出现分段错误
Get segmentation fault when manipulating with malloc in c
我正在实施一个程序,将 a
数组中的所有值除以 100
,然后使用 malloc
将它们存储在 b
数组中。问题是在 main
.
中打印 b
的值时出现分段错误
这是我的代码
#include <stdio.h>
#include <stdlib.h>
void divide(int *a, int n, double *b){
b=malloc(n*sizeof(double));
for(int i=0; i<n; i++){
b[i]=(double)a[i]/100.0;
}
//check: values still remain in b
for (size_t i = 0; i < 5; i++)
{
printf("%.2f ", b[i]);
}
}
int main(){
int a[]={1,2,3,4,5};
double *b;
divide(a,5,b);
//check: lost value and cause segmentation fault
for (size_t i = 0; i < 5; i++)
{
printf("%.2f ", b[i]);
}
free(b);
return 0;
}
那么是什么原因导致了这个问题以及如何解决它?
提前致谢。
您正在将指针 b 按值传递给函数 divide
divide(a,5,b);
即函数处理原始指针的副本。更改副本不会影响原始指针。
您需要通过指向它的指针按引用传递指针,或者重新设计函数,使其 return 指向函数内动态分配内存的指针。
例如,可以按以下方式声明和定义函数
double * divide( const int *a, size_t n )
{
double *b = malloc( n * sizeof( double ) );
if ( b != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
b[i] = a[i] / 100.0;
}
//check: values still remain in b
for ( size_t i = 0; i < n; i++ )
{
printf("%.2f ", b[i]);
}
}
return b;
}
在主要部分你可以写
double *b = divide( a, sizeof( a ) / sizeof( *a ) );
否则函数看起来像
void divide( const int *a, size_t n, double **b )
{
*b = malloc( n * sizeof( double ) );
if ( *b != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
( *b )[i] = a[i] / 100.0;
}
//check: values still remain in b
for ( size_t i = 0; i < n; i++ )
{
printf("%.2f ", ( *b )[i]);
}
}
}
并称赞
divide( a, sizeof( a ) / sizeof( *a ), &b );
函数divide接收的是指针b的副本。这意味着函数main中的变量b在调用后没有变化。一个更简单的例子来说明这一点是
void f(int n)
{
n = 1;
}
调用f后,调用方n不变
最简单的代码更正是让 divide 接收指向指针 b 的指针。 divide 的签名将是
void divide(int *a, int n, double **b);
但是,最好在同一个函数中分配和释放内存,因为很容易忘记 divide 分配内存。在处理数组时,我总是使用两个方便的宏函数 NEW_ARRAY 和 LEN 来简化代码。下面是我的建议。如果更改 a 的长度,其余代码将很好地遵循。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN(array) (sizeof (array) / sizeof (array)[0])
#define NEW_ARRAY(pointer, length) \
{ \
(pointer) = malloc(((size_t) length) * sizeof (pointer)[0]); \
if ((pointer) == NULL) { \
fprintf(stderr, "Allocating memory with malloc failed: %s\n", strerror(errno)); \
exit(EXIT_FAILURE); \
} \
}
void divide(int *a, int n, double *b)
{
for (int i = 0; i < n; i++) {
b[i] = a[i] / 100.0;
}
}
int main(void)
{
int a[] = {1, 2, 3, 4, 5};
double *b;
NEW_ARRAY(b, LEN(a));
divide(a, LEN(a), b);
for (size_t i = 0; i < LEN(a); i++) {
printf("%.2f ", b[i]);
}
printf("\n");
free(b);
return 0;
}
我正在实施一个程序,将 a
数组中的所有值除以 100
,然后使用 malloc
将它们存储在 b
数组中。问题是在 main
.
b
的值时出现分段错误
这是我的代码
#include <stdio.h>
#include <stdlib.h>
void divide(int *a, int n, double *b){
b=malloc(n*sizeof(double));
for(int i=0; i<n; i++){
b[i]=(double)a[i]/100.0;
}
//check: values still remain in b
for (size_t i = 0; i < 5; i++)
{
printf("%.2f ", b[i]);
}
}
int main(){
int a[]={1,2,3,4,5};
double *b;
divide(a,5,b);
//check: lost value and cause segmentation fault
for (size_t i = 0; i < 5; i++)
{
printf("%.2f ", b[i]);
}
free(b);
return 0;
}
那么是什么原因导致了这个问题以及如何解决它?
提前致谢。
您正在将指针 b 按值传递给函数 divide
divide(a,5,b);
即函数处理原始指针的副本。更改副本不会影响原始指针。
您需要通过指向它的指针按引用传递指针,或者重新设计函数,使其 return 指向函数内动态分配内存的指针。
例如,可以按以下方式声明和定义函数
double * divide( const int *a, size_t n )
{
double *b = malloc( n * sizeof( double ) );
if ( b != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
b[i] = a[i] / 100.0;
}
//check: values still remain in b
for ( size_t i = 0; i < n; i++ )
{
printf("%.2f ", b[i]);
}
}
return b;
}
在主要部分你可以写
double *b = divide( a, sizeof( a ) / sizeof( *a ) );
否则函数看起来像
void divide( const int *a, size_t n, double **b )
{
*b = malloc( n * sizeof( double ) );
if ( *b != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
( *b )[i] = a[i] / 100.0;
}
//check: values still remain in b
for ( size_t i = 0; i < n; i++ )
{
printf("%.2f ", ( *b )[i]);
}
}
}
并称赞
divide( a, sizeof( a ) / sizeof( *a ), &b );
函数divide接收的是指针b的副本。这意味着函数main中的变量b在调用后没有变化。一个更简单的例子来说明这一点是
void f(int n)
{
n = 1;
}
调用f后,调用方n不变
最简单的代码更正是让 divide 接收指向指针 b 的指针。 divide 的签名将是
void divide(int *a, int n, double **b);
但是,最好在同一个函数中分配和释放内存,因为很容易忘记 divide 分配内存。在处理数组时,我总是使用两个方便的宏函数 NEW_ARRAY 和 LEN 来简化代码。下面是我的建议。如果更改 a 的长度,其余代码将很好地遵循。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN(array) (sizeof (array) / sizeof (array)[0])
#define NEW_ARRAY(pointer, length) \
{ \
(pointer) = malloc(((size_t) length) * sizeof (pointer)[0]); \
if ((pointer) == NULL) { \
fprintf(stderr, "Allocating memory with malloc failed: %s\n", strerror(errno)); \
exit(EXIT_FAILURE); \
} \
}
void divide(int *a, int n, double *b)
{
for (int i = 0; i < n; i++) {
b[i] = a[i] / 100.0;
}
}
int main(void)
{
int a[] = {1, 2, 3, 4, 5};
double *b;
NEW_ARRAY(b, LEN(a));
divide(a, LEN(a), b);
for (size_t i = 0; i < LEN(a); i++) {
printf("%.2f ", b[i]);
}
printf("\n");
free(b);
return 0;
}