malloc函数分配内存失败的原因及解决方法

malloc函数分配内存失败的原因及解决方法


先说结论

malloc()函数分配内存失败的原因:
1. 内存不足。
2. 在前面的程序中出现了内存的越界访问,导致malloc()分配函数所涉及的一些信息被破坏。下次再使用malloc()函数申请内存就会失败,返回空指针NULL(0)

解决方法:
1.在STM32中堆空间内存不足的解决方法可以参考我上一篇文章

STM32分配堆栈空间不足问题原因及解决方法 http://blog.csdn.net/lighthear/article/details/69485942

2.从不能分配的那个malloc()函数开始,往回找最近的那个能分配的malloc()函数,出问题的代码应该就在这部分,很可能的原因就是指针越界,对未知的内存进行了操作,导致了malloc()不能继续分配内存。


遇到的问题

       最近遇到STM32创建链表时,第一次运行正常,第二次无法正常创建的问题。在线调试发现是malloc()函数没有分配到内存,但是我之前已经调大过内存空间了,不应该存在小数据也内存不足的情况。


解决方法

       刚开始以为是由于第一次运行后的释放内存操作没有正常执行,导致浪费过多内存空间产生内存不足,尝试了多种方式重写释放的函数,也查阅了free()函数的用法,证明使用方式正确。问题未解决

       后来猜测由于指针变量释放后没有指向NULL,造成了野指针的情况。但是所有指针变量均为局部变量,程序执行结束之后会自动释放,并不会对下次造成影响。问题未解决

       查阅网上的资料发现,malloc()内存分配失败的原因,除了内存不足,还可能是之前产生了内存指针越界。

malloc()函数分配内存失败的原因:
1. 内存不足。
2. 在前面的程序中出现了内存的越界访问,导致malloc()分配函数所涉及的一些信息被破坏。下次再使用malloc()函数申请内存就会失败,返回空指针NULL(0)

在这个思想指导下,往前逐个查找可能发生指针越界的函数

unsigned char * StrArray_ValArray(char *pStrArray)
{
    int valArraySize = strlen(pStrArray) / 2;       
    unsigned char *pValArray;
    pValArray = (unsigned char *)malloc(sizeof(unsigned char) * valArraySize);
    for (int i = 0; i < valArraySize; i++)
    {
        sscanf(pStrArray + i * 2 ,"%2x",(unsigned int *)(pValArray + i));    //强制类型转换造成指针越界
    }
}

       发现,声明的pValArrayunsigned char *类型的指针,由于sscanf()的第三个参数提示需要unsigned int *类型的变量,因此对pValArray做了强制类型转换,从unsigned char *变为了unsigned int *。虽然对于pValArray来说,内存空间没变(都为指针,32位系统分配4字节),但是对于编译器来说,所指向数据的含义就从unsigned char扩大到了unsigned int,之后通过指针遍历访问,对数组进行更改就会造成指针越界,更改到未分配的区域。因此下次再使用malloc()函数申请内存就会失败,返回空指针NULL(0)

       因此将干脆将pValArray直接定义成unsigned int *类型的变量,并按照unsigned int类型分配空间,而不进行强制类型转换。这样就可避免指针越界的情况。测试发现问题不再发生。问题解决


总结

       如果下一次再碰到这样的问题,就从不能分配的那个malloc()函数开始,往回找最近的那个能分配的malloc()函数,出问题的代码应该就在这部分,很可能的原因就是指针越界,对未知的内存进行了操作,导致了malloc()不能继续分配内存。

       因此以后对指针的操作一定要万分小心,防止指针越界问题的发生。

参考文章:
1. malloc函数申请内存失败,返回空NULL(0):http://blog.csdn.net/gadflycq/article/details/40752373
2. 在内存充足时malloc函数分配内存失败的原因及解决:http://blog.sina.com.cn/s/blog_71d3b5480100lxcx.html

  • 55
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
《C语言程序设计》 实验指导书 山东水利职业学院 目 录 实验一 C语言程序初步 2 实验二 数据类型、运算符和表达式 3 实验四 循环结构(1) 6 实验五 循环结构(2) 9 实验六 函数(1) 12 实验七 函数(2) 14 实验八 数组(1) 16 实验九 数组(2) 19 实验十 指 针 (1) 22 实验十一 指针(二) 24 实验十二 有关文件的程序设计 27 实验十三 结构体和共用体 30 实验十四 位运算 32 实验十五 综合应用举例 33 实验一 C语言程序初步 [实验目的和要求] 1、 熟悉C语言运行环境。 2、 掌握C语言程序的书写格式和C语言程序的结构。 3、 掌握C语言上机步骤,了解运行一个C程序的方法。 4、 本实验可在学习完教材第一章后进行。 [实验内容和步骤] 1、输入一个简单的C语言程序:输入矩形的两条边,求矩形的面积。 [分析与讨论] 1、记下在调试过程中所发现的错误、系统给出的出错信息和对策。分析讨论对策成功或失败原因。 2、总结C程序的结构和书写规则。 实验二 数据类型、运算符和表达式 [实验目的] 1.熟练表达式的表示方法 2.了解表达式的运行结果 3.了解C语言中数据类型的意义 [实验内容和步骤] 1. 用printf函数来输入表达式运行结果 2. 程序试图计算由键盘输入的任意两个整数的平均值: [问题讨论] 1.“=”和“==”有什么区别? 2.“&”和“&&”、“|”和“||”有什么区别? 3. 如何正确地选用数据类型? 实验三 选择结构 [实验目的] 1、了解条件与程序流程的关系 2、了解用不同的数据使程序的流程覆盖不同的语句、分支和路径。 [实验内容和步骤] 1、题目 有如下程序段: {…… if (a>1&&b= =0) x=x/a; if(a==2||x>1) x=x+1; } 为了更容易明白程序的逻辑结构,要求用流程图来加以描述。 要求增加一些输入语句和输出语句,以便使上述程序能在不同的a,b和x值下运行,并且能观察程序流程经过(覆盖)了哪些语句、哪些分支及哪些路径。 [分析讨论] (1) 用哪一组数据就可使程序中的每个处理语句都执行一次?为了找出程序中各条处理语句中的错误,应该使用什么样的数据对程序进行测试?请上机验证自己的结论。 (2) 用哪两组数据就可以使程序段中的每个分支都运行一次?这种情形与上面的讨论有何不同?如果为了找出程序中积压分支中的错误,应该使用什么样的数据对程序进行测试?请上机验证自己的结论。 (3)用哪两组数据就可以把判定框中的每个条件运算都进行一次?如果为了测试出判定条件中的错误,应使用哪些数据对程序进行测试?请上机验证自己的结论。 (4)用哪四组数据才可以把各种条件的组合都检测一遍? 如果为了测试各种条件的组合的情形,应该使用什么样的测试数据?请上机验证自己的结论。 (5)用哪四组数据才可以把起始到终止的各条路径都覆盖一次?如果为了测试出程序在不同路径下的错误,应该使用什么样的测试数据?请上机验证自己的结论。 实验四 循环结构(1) [目的和要求] 1、掌握在程序设计条件型循环结构时,如何正确地设定循环条件,以及如何控制循环的次数。 2、了解条件型循环结构的基本测试方法。 [实验内容与步骤] 1、下面是一个计算e的近似值(使误差小于给定的δ)的程序。 main() {double e=1.0,x=1.0,y,detax; int i=1; printf(“\n please input enter a error:”); scanf(“%lf”,&detax); y=1/x; while(y>=detax) { x=x*I; y=1/x; e=e+y; ++i; } printf(“%12.10lf”,e); } [分析讨论] (1)、阅读上面的程序,写出程序所依据的计算公式。 (2)、当输入的detax各是什么值时,能分别使程序按下面的要求运行: .不进入循环; .只循环一次; .只循环两次; .进入死循环(程序将永远循环下去)。 为了能知道程序循环了多少次,应该在程序中增加一条什么样的语句? (3)、原程序中while语句中的y>=detax,分别换成y>detax,y=detax,y<detax,y<=detax,观察程序运行将会有什么变化。 假如不知道机器内的程序中的各语句实际上是什么,分别输入什么样的detax来测试出while语句的循环条件写错了。 (4)、把原程序中while语句之前的y=1/x语句去掉,观察程序的运行将会发生什么样的变化。 假如不知道机器内的程序实际上是怎么写的,输入什么样的detax就能测试出少了上述这条语句。 (5)、若把原程序中的++i换成i++,观察程序的运行发生了什么变化? 假如不知道这条语句到底是怎么写的,输入什么样的detax就能测试出这条语句写错了. (6)、把原程序中的while结构改写成do—while结构,再分别按上述的(2)、(3)两步进行实验。 实验五 循环结构(2) [ 目的和要求] 1、 掌握如何正确地控制计数型循环结构的次数 2、 了解对计数型循环结构进行测试的基本方法 3、 了解在嵌套循环结构中,提高程序效率的方法 4、 本实验应在学习了教材第3.3.4进行 [实验内容与步骤] 实验题目:下面是一个循环结构 的C程序。 main() { int i ,j; long sum=0; for(i=1,i<=20,i++) for(j=1;j<=3;j++) sum=sum+(i+1)*(i+1)*(j+2) printf(“sum is :%d\n”,sum); } [ 分析讨论] (1) 将上述程序中的和分别做什么样修改,能使程序按如下要求运行: .不循环; .外循环1次,不进入内循环; .外循环,内循环各1次; .外循环1次,内循环2次; .外循环 2次, 内循环1次; .外循环19次,内循环3次; .外循环20次,内循环2次; .外循环21次,内循环3次。 (2) 试修改程序,以便能知道控制表达式 i=1;j<=20;i++ 和 j=1;j<3;j+= 各执行了多少次? (3)内循环与外循环的控制表达式进行对换,观察程序的执行结果有无变化,并且观 察对换后的外循环与内循环控制表达式执行的总次数有无变化? (4)将(3)中程序写为 main() { int i,j,k; long sum=0; for (j=1.j<=3.j++) { k=j+2; for(i=1;i<=20;i++) sum=sum+(i+1)*(i+1)**k; } printf(“sum is :%d\n”,sum); } 观察程序的执行结果有无变化? (5)将(3)中程序改写为 main() { int I,j,m,n; long sum=0; for(j=1;j<=3;j++) { m=j+2; for(I=1;j<=20;I++) { n=I+1; sum=sum+m*m*k; } } printf(“sum is :%d\n”,sum); } 观察程序的执行结果有无变化? (1) 实验六 函数(1) [实验目的] 1.理解和掌握多模块的程序设计与调试的方法。 2.掌握函数的定义和调用的方法。 3.学会使用递归方法进行程序设计。 [实验内容和步骤] 1. 编写一个函数,判断一个数是不是素数。在主函数中输入一个整数,输出是否是素数的信息。 实验步骤与要求: (1) 编写一个函数prime(n),返回给定整数n是否为素数。 (2) 编写一个主函数,输入一个整数,调用(1)中的函数,判断此整数是否为素数,并输出结果。 (3) 对于属于多函数程序,可以采用每个函数分别进行编辑、编译的方法,然后再连接、运行。如果编译有错时,可分别修改,这样便于调试。实验2和实验3也可以使用这样的调试方法。 2. 用梯形法求函数的定积分。 实验步骤与要求: (1) 编制一个函数sab(a,b,n),其功能是求函数f(x)在[a,b]上的定积分,其中n为区间[a,b]的等分数。要求该函数在一个独立的文件中。 (2) 编制一个主函数以及计算被积函数值的函数f(x),在主函数中调用(1)中的函数计算并输出下列积分值。要求主函数与函数f(x)在同一个文件中。 (3) 编制另一个主函数以及计算被积函数值的函数f(x),在主函数中调用(1)中的函数计算并输出下列积分值。要求主函数与函数f(x)在同一个文件中。 说明: 用梯形法求定积分,梯形公式为 s=h[f(a)+f(b)]/2+hf(a+kh)其中,h=(b-a)/n 3. 用递归方法编写程序,求n阶勒让德多项式的值,递归公式为 1 (n=0) pn(x)=x (n=1) ((2n-1)xpn-1(x)-(n-1)pn-2(x))/n (n>1) , [ 分析讨论] 1. 小结函数的定义及调用方法。 2. 小结函数中形参和实参的结合规则。 实验七 函数(2) [目的与要求] 1、 掌握C语言函数定义及调用的规则。 2、 理解参数传递的过程。 [ 实验内容与步骤] 1、 上机调试下面的程序,记录系统给出的出错信息,并指出出错原因。 main() { int,y; printf(“%d\n”,sum(x+y)); int sum(a,b) { int a,b; return(a+b); } } 2、 编写并调试一个求(n为整数)的递归函数,希望能在程序运行过程中动态地显示递归函数被调用的轨迹。 [分析讨论] 1、 针对以上实验内容写出相应的参数传递过程并分析结果。 2、 讨论参数的传递的几种形式。 实验八 数组(1) [实验目的] 掌握有关数组和字符串的程序设计方法。 [实验内容和步骤] 1 已知一组数据如下: 6,3,42,23,35,71,98,67,56,38 编写程序,把它们按从小到大的次序排列起来。 程序如下: /*EX3-1*/ # include<stdio.h> # define N 10 main() { int a[N]={6, 3, 42, 23, 35, 71, 98, 67, 56, 38}; int i, j, t; printf(“The array before sorted:”); for(i=0; i<N; i++) printf(“%4d”, a[i]); for(i=0; i<9; i++) { for(j=i+1; j<10; j++) { if(a[i]>a[j]) { t=a[i]; a[i]=a[j]; a[j]=t; } } } for(i=0; i<N; i++) printf(“%4d”, a[i]); return o; } [ 分析讨论] 1. 定义数组时下标的用法和注意事项. 2.什么情况下出现下标越界.  实验九 数组(2) [目的和要求] 1、掌握数组定义的规则。 2、掌握C语言数组的基本用法。 [实验内容与步骤] 1、编写程序,测试下列数组的定义方式是否正确 (1) main() { int n; scanf(“%d”,&n); int a[n]; …… } (2) main() { const int n=10; int a[n]; } (3) #include <stdio.h> #define M 10 main() { int a[M]; } (4) main() { int a[2+2*4]; } (5) #include <stdio.h> #define M 2 #define N 8 main() { int a[M+N]; } 通过这一实验,可以说明什么问题? 2、运行下面的C程序,根据运行结果,可以说明什么? main( ) { int num[5]={1,2,3,4,5}; inti i; for(i=0;i<=5;i++) printf(“%d”,num[i]); } 3、操作符&用以求一个变量的地址,这在函数scanf中已经使用过了。现在要你设计一个程序,返回一个3 * 5 的二维数组各元素的地址,并由此说明二维数组中各元素是按什么顺序存诸的。 4、为一个起泡排序程序设计测试用例,并测试之。 [分析讨论] 通过实验,分析定义与引用数组的区别。 实验十 指 针 (1) [目的和要求] 1. 熟悉指针的正确用法。 [实验内容和步骤] 1、指出下面程序错误的原因。 main( ) { int x=10,y=5,*px,*py; px=py; px=&x; py=&y; printf(“*px=%d,*py=%d,*px,*py); } 2.下面的程序能获得上述运行结果吗? main() { char *S=”COMPUTER”; char c; printf(“which style you want to \n”); printf(“capital (c) or uncapital(u);”); c=getchar(); if(c=’c’) put(s); else { s=”computer”; puts(s); } } 分析出错原因。 3.设计一个C程序,用以测试下列各表达式的运算。 (1) y=*px++ (2) y=*++py (3) y=(*py)++ (4) y=--*ppx++ [分析讨论] 数组与指针的联系。 实验十一 指针(二) [目的和要求] 1、了解指针参数的特殊性。 2、掌握函数、指针、数组的用法。 [实验内容与步骤] 1、想使指针变量pt1指向a 和b 中的大者,pt2指向小者,以下程序能否实现此目的? swap(int *p1,int *p2) { int *p; p=p1;p1=p2;p2=p; } main() { int a,b; scanf(“%d,%d”,&a,&b); pt1=&a;pt2=&b; if(a<b)swap(pt1.pt2); printf(“%d,%d\n”,*pt1,*pt2); } 上机调试此程序。如果不能实现题目要求,指出原因,并修改之。 2、 下面的程序。注意其中的复杂声明语句; int (*function[4])(); 和各标记符的含义,并记录执行结果。 main() { int fun1(); int fun2(); int fun3(); int fun4(); int (*function[4])(); int a=10,b=5,i; function[0]=fun1; function[1]=fun2; function[2]=fun3; function[3]=fun4; for(I=0;I<4;i++) printf(“fun no.%d->%d\n”,i+1,execute(a,b,function[i])); } execute(int x,int y,int *fun()) { return(*fun)(x,y);} fun1(int x, int y) { return(x+y);} fun2(int x,int y) { return(x-y);} fun3(int x,int y) { return(x*y);} fun4(int x,int y) { return(x/y);} [分析讨论] 指针、数组、函数的联系。 实验十二 有关文件的程序设计 [实验目的] 1. 掌握文件建立的方法。 2. 掌握包含文件操作的程序设计和调试方法。 [实验内容和步骤 ] 1 建立一个磁盘文件,其内容是0~90°之间每隔5°的正弦值。 程序如下: //EX8-1 #include<iostream.h> #include<fstream.h> #include<math.h> #define PI 3.14159 main() { float S[19]; int i, a; ofstream out(“fsin.bny”); if(!out) { cout<<”Cannot open file.”<<endl; return 1; } for(i=0,a=-5; i<19; i++) { a+=5; S[i]=sin(a*PI/180.0); } out.write((unsigned char*)&s, sizeof s); out.close( ); return 0; } [ 分析讨论] 文件操作中各函数的功能,具体使用方法. 实验十三 结构体和共用体 [目的和要求] 1、掌握结构体类型方法以及结构体变量的定义和引用。 2、掌握指向结构体变量的指针变量的应用,特别是链表的应用。 3、掌握运算符”.”和”->”的应用。 4、共用体的概念和应用。 [实验内容和步骤] 1、编写程序:有4名学生,每个学生的数据包括学号、姓名、成绩,要求找出成绩最高者的姓名和成绩,上机运行程序。 2、建立一个链表每个结点包括的成员为:职工号、工资。用malloc打印出来。用一个creat 来建立链表,用list来输出数据。5个职工号为101,103,105,107,109。 3、在上题基础上,新增加一个职工的数据,按职工号的顺序插入链表,新插入的职工号为106。写一函数insert来插入新结点。 4、在上面的基础上,写一函数delete,用来删除一个结点。要求删除职工号为103的结点。打印出删除后的链表. 5、你有无办法测试构造链表时,内存空间的动态分配情形? [分析讨论] 怎样引用结构体变量成员? 实验十四 位运算 [目的和要求] 1. 掌握位运算的概念和方法。 2. 掌握位运算(&,|,^,~)的使用方法。 3. 掌握有关位运算的用法。 [实验内容和步骤] 1. 按习题8.2的要求,编一个程序,将一个整数的高字节和低字节分别输出(用位运算方法)。上机运行。 2. 按习题8.6的要求,编一个程序,使一个整数的低4位翻转。上机运行,用十六进制数输入和输出。 3. 按习题8.10的要求,将一个整数i的各位循环左移4位,设i的值为十六进制数fe13。 4. 按习题8.13的要求,设计一个函数,当给定一个整数后,能得到该数的补码(应考虑该整数是正数或负数)。 [分析讨论] 位运算时应注意什么问题? 实验十五 综合应用举例 [目的与要求] 1、熟悉C语言的端口及硬件控制的方法与原理。 2、了解用C语言实现发声程序所要访问的端口。 [实验内容和步骤] 1、调试课本中例10.8程序,注意调出不同的效果。 2、调试并总结程序中所用的知识点,写出乐谱文件播放的是什么乐谱? 乐谱实例: 6000 h5 1 h3 2 h2 0.5 h3 0.5 h1 4 h2 1 m7 2 m6 0.5 h1 0.5 m5 4 m3 2 m5 1.5 m6 0.5 h1 1.5 h2 0.5 m6 0.5 h1 0.5 m5 1 h5 1.5 h1 0.5 h6 0.5 h5 0.5 h3 0.5 h5 0.5 h2 4 h2 1.5 h3 0.5 m7 1 m6 1 m5 1.5 m6 0.5 h1 1 h2 1 m3 1 h1 1 m6 0 m5 0.5 m6 0.5 h1 0.5 m5 4 h3 1.5 h5 0.5 m7 1 h2 1 m6 0.5 h1 0.5 m5 3 m3 0. m5 0.5 m3 0.5 m5 0.5 m5 0.5 m6 0.5 m7 0.5 h2 0.5 m6 3 m5 0.5 m6 0.5 h1 1.5 h2 0.5 h5 1 h3 1 h2 1 h3 0.5 h2 0.5 h1 1 m6 0.5 m5 0.5 m3 2 h1 2 m6 0.5 h1 0.5 m6 0.5 m5 0.5 m3 0.5 m5 0.5 m6 0.5 h1 0.5 m5 3 h3 0.5 h5 0.5 h2 0.5 h3 0.5 h2 0.5 h1 0.5 m7 1 m6 1 h5 4## void play_music(char *filename) /*filename为音乐文件名格式见上*/ { FILE *fp; int rate; char sound_high[3]; float sound_long; register int i=0,j; int sign=0; float str[1000][2]; if ((fp=fopen(filename,"r"))==NULL) { printf("Open file music.doc Errors!\n"); exit(1); } fscanf(fp,"%d",&rate); while(!feof(fp)&&!sign) { fscanf(fp,"%s%f",&sound_high,&sound_long); str[i][1]=rate*sound_long; switch(sound_high[0]) { case 'h': switch(sound_high[1]) { case '1': str[i++][0]=1046.5; break; case '2': str[i++][0]=1174.7; break; case '3': str[i++][0]=1318.5; break; case '4': str[i++][0]=1396.9; break; case '5': str[i++][0]=1568; break; case '6': str[i++][0]=1760; break; case '7': str[i++][0]=1975.5; break; default: printf("\n Error Music.doc\n"); break; } break; case 'm': switch(sound_high[1]) { case '1': str[i++][0]=523.3; break; case '2': str[i++][0]=587.3; break; case '3': str[i++][0]=659.3; break; case '4': str[i++][0]=698.5; break; case '5': str[i++][0]=784.0; break; case '6': str[i++][0]=880; break; case '7': str[i++][0]=987.8; break; default: printf("\n Error music.doc.\n"); break; } break; case 'l': switch(sound_high[1]) { case '1': str[i++][0]=262; break; case '2': str[i++][0]=296; break; case '3': str[i++][0]=329.6; break; case '4': str[i++][0]=349.2; break; case '5': str[i++][0]=392; break; case '6': str[i++][0]=440; break; case '7': str[i++][0]=493.9; break; default: printf("\n Error music.doc.\n"); break; } break; case '*': switch(sound_high[1]) { case '1': str[i++][0]=131; break; case '2': str[i++][0]=147; break; case '3': str[i++][0]=165; break; case '4': str[i++][0]=176; break; case '5': str[i++][0]=196; break; case '6': str[i++][0]=220; break; case '7': str[i++][0]=247; break; default: printf("\n Error music.doc\n"); break; } break; case '#': if (sound_high[1]=='#') sign=1; break; case 'x': if (sound_high[1]=='0') str[i++][0]=20; break; default:printf("\n ERRor music.doc\n"); exit(1); } } for(j=0;j<=i-1;j++) { sound(str[j][0]); delay(str[j][1]); } nosound(); } [分析讨论] 1.c语言怎样对数据库进行管理? 2.分析程序设计过程中怎样对基础知识进行灵活运用。
C函数库手册,按照函数功能来分类 分类函数,所在函数库为ctype.h int isalpha(int ch) 若ch 是字母('A'-'Z','a'-'z')返回非0 值,否则返回0 int isalnum(int ch) 若ch 是字母('A'-'Z','a'-'z')或数字('0'-'9')返回非0 值,否则返回0 ...... 数学函数,所在函数库为math.h、stdlib.h、string.h、float.h int abs(int i) 返回整型参数i 的绝对值 double cabs(struct complex znum) 返回复数znum 的绝对值 double fabs(double x) 返回双精度参数x 的绝对值 ...... 目录函数,所在函数库为dir.h、dos.h int chdir(char *path) 使指定的目录path(如:"C:\\WPS")变成当前的工作目录,成 功返回0 int findfirst(char *pathname,struct ffblk *ffblk,int attrib)查找指定的文件,成功 返回0 ...... 进程函数,所在函数库为stdlib.h、process.h void abort() 此函数通过调用具有出口代码3 的_exit 写一个终止信息于stderr,并异常终止程序。无返回值 int exec…装入和运行其它程序 ...... 转换子程序,函数库为math.h、stdlib.h、ctype.h、float.h char *ecvt(double value,int ndigit,int *decpt,int *sign)将浮点数value 转换成字符串并返回该字符串 char *fcvt(double value,int ndigit,int *decpt,int *sign)将浮点数value 转换成字符串并返回该字符串 ...... 诊断函数,所在函数库为assert.h、math.h void assert(int test) 一个扩展成if 语句那样的宏,如果test 测试失败,就显示一个信息并异常终止程序,无返回值 void perror(char *string) 本函数将显示最近一次的错误信息,格式如下:字符串string:错误信息 ...... 输入输出子程序,函数库为io.h、conio.h、stat.h、dos.h、stdio.h、signal.h int kbhit() 本函数返回最近所敲的按键 int fgetchar() 从控制台(键盘)读一个字符,显示在屏幕上 ...... 接口子程序,所在函数库为:dos.h、bios.h unsigned sleep(unsigned seconds)暂停seconds 微秒(百分之一秒) int unlink(char *filename)删除文件filename unsigned FP_OFF(void far *farptr)本函数用来取远指针farptr 的偏移量 ...... 存贮分配子程序,所在函数库为dos.h、alloc.h、malloc.h、stdlib.h、process.h int allocmem(unsigned size,unsigned *seg)利用DOS 分配空闲的内存,size 为分配内存大小,seg 为分配后的内存指针 int freemem(unsigned seg)释放先前由allocmem 分配的内存,seg 为指定的内存指针 ...... 操作函数,所在函数库为string.h、mem.h mem…操作存贮数组 ...... ......
当使用malloc函数申请内存时,如果申请的内存过大,可能会导致内存分配失败。这是因为操作系统在分配内存时,需要在内存中找到一块足够大的连续空间来满足申请。如果没有足够大的连续空间,就会分配失败。在这种情况下,可以考虑使用realloc或calloc函数来代替malloc函数。 如果使用realloc函数,可以先使用malloc函数申请一部分内存,然后在需要时使用realloc函数重新分配内存。如果realloc函数无法分配足够大的内存,它将返回NULL指针,此时可以考虑使用calloc函数。 如果使用calloc函数,它将分配一块指定大小的内存,并将其初始化为0。与malloc函数不同,calloc函数不需要连续的空间,因此可以更好地处理大内存分配问题。 下面是一个使用realloc函数重新分配内存的例子: ```c #include <stdio.h> #include <stdlib.h> int main() { int *ptr; int n = 5, i; // 分配初始内存 ptr = (int*) malloc(n * sizeof(int)); // 检查内存是否分配成功 if (ptr == NULL) { printf("Memory allocation failed\n"); exit(1); } // 输出初始内存中的值 printf("Initial memory allocation:\n"); for (i = 0; i < n; i++) { printf("%d ", *(ptr + i)); } // 重新分配内存 n = 10; ptr = (int*) realloc(ptr, n * sizeof(int)); // 检查内存是否分配成功 if (ptr == NULL) { printf("Memory allocation failed\n"); exit(1); } // 输出重新分配后的内存中的值 printf("\nMemory reallocation:\n"); for (i = 0; i < n; i++) { printf("%d ", *(ptr + i)); } // 释放内存 free(ptr); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值