在使用malloc函数时遇见的常见错误

malloc函数简介

malloc函数在C语言和C++中经常使用,为变量动态分配内存空间。

函数原型 void malloc(int size)
说明:malloc 向系统申请分配指定size个字节的内存空间。如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
该函数包含在头文件:#include <malloc.h>中 ,使用时需导入头文件
*<malloc.h>或者<stdlib.h>** 。注意!当内存不再使用时,应使用free()函数将内存块释放。

常见用法

  1. 在不知道变量需要的确定内存时,比如在定义一个数组时,数组的大小在程序编译后才知道,这时可以用malloc函数。
int main()
{
	int n;
	scanf("%d",&n);
	int *m=(int *)malloc(sizeof(int)*n);  //定义了一个指向n个int的	 指针变量,相当于开了一个n个int元素的数组。
	//如果n很大,超过1000000,那么开一个这么大的int型数组就会发生栈溢出。
	int m[1000000]; //会发生栈溢出。
	return 0;
}
  1. 为结构体变量分配空间。
    如果定义一个结构体类型的普通变量,可以不malloc动态申请内存,CPU会为这个结构体变量分配内存 。
typedef struct
{
    int n;
    char *p;
}node;

int  main()
{
	node a;  //定义的是结构体普通变量,可以不使用malloc申请内存,CPU会为这个结构体变量分配内存
    a.n=4;
    printf("%d",a->n);  //可以成功输出
    node *b;  //定义的是结构体指针变量,CPU会为这个指针开辟内存,大小为4个字节。但是要存储结构体的数据成员这个空间不够,会引发段错误,此时必须要malloc申请一个结构体类型大小的动态内存,存储数据成员。
    //b=(node *)malloc(sizeof(node));
    printf("%d",sizeof(b)); //用sizeof(b)查看b的大小为4
    char p[]="abcd";
    printf("%d",b->n);
    (a->p)=p;
    printf("%c",a->p[0]);
    return 0;
}

没有使用malloc为结构体指针变量b分配空间,会报warning: ‘b’ is used uninitialized in this function [-Wuninitialized]|。

  1. 在定义结构体时需要注意,要依次为其成员分配空间。
    在平常使用过程中,在用malloc函数为某个结构体分配空间后,在对其成员变量(指针类型)进行操作,比如 令该指针 p=NULL时,总会报“Program received signal SIGSEGV, Segmentation fault."(程序收到信号SIGSEGV,分段故障).

比如,今天在用邻接顺序表实现一个有向带权图时,就再次报了这个错误“Program received signal SIGSEGV, Segmentation fault."。

#include <stdio.h>
#include <malloc.h>
#define Max 100;

using namespace std;

typedef struct Node   //单链表中的每个节点
{
    int adjvex;   //边表节点中的顶点编号
    int weight;
    struct Node *next;
}AdjNode;
typedef struct Hnode  //单链表的头节点,每一个表头节点存放图中每个点的信息
{
    int no;
    AdjNode *first;
}AdjHead;      //每个顶点的表头节点
typedef struct   //图
{
    int n,e;
    AdjHead *node[Max];
}AdjGraph;

void CreateGraph(AdjGraph *G,int edge[Max][Max],int n,int e)
{
	//使用malloc为结构体图G分配空间
    G=(AdjGraph *)malloc(sizeof(AdjGraph));
    G->n=n;
    G->e=e;
    for(int i=0;i<n;i++)
    {
        //思考为什么还要用malooc为G->node[i](每个表头)分配空间?
        //如果不写,调试时会报Program received signal SIGSEGV, Segmentation fault."
        G->node[i]=(AdjHead *)malloc(sizeof(AdjHead));
        G->node[i]->first=NULL;   //先把每个表头节点置为空
        G->node[i]->no=i;
        AdjNode *p;
        for(int j=n-1; j>0;j--)
        {
            if(edge[i][j]!=0 && edge[i][j]!=INF)
            {
                p=(AdjNode *)malloc(sizeof(AdjNode));
                p->adjvex=j;
                p->weight=edge[i][j];
                p->next=G->node[i]->first;
                G->node[i]->first=p;    //头插法建立单链表
            }
        }
    }
    printf("创建成功!\n");
}
//说明:在main()函数里已经使用 G2=(AdjGraph *)malloc(sizeof(AdjGraph));为G分配了空间。

疑问:不是函数里已经使用 G=(AdjGraph *)malloc(sizeof(AdjGraph))分配了空间嘛?为什么还要使用 malloc函数为每个表头节点分配空间,才能对表头节点G->node[i]内部的指针成员变量进行置空操作?
回答:因为G=(AdjGraph *)malloc(sizeof(AdjGraph))只是为n,e,和node[max]这个数组分配了空间,数组里面存放的是结构体类型的指针,指针只占4个字节(32位CPU),而该指针指向的变量为AdjHead类型(结构体),该类型变量所占用的空间不只4个字节,所以对该变量进行操作时还需要动态分配空间。

总结:如果定义一个结构体类型的普通变量,可以不malloc动态申请内存,CPU会为这个结构体变量分配内存 。
如果定义的是一个结构体的指针,CPU会为这个指针开辟内存,但是此时这个大小是4(32位的CPU),该空间的大小不够存储数据成员,所以在使用该结构体数据成员时,还要malloc申请相应结构体类型大小的动态内存,用于数据成员存储使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值