c语言函数调用!!求哪位大神解释下这两个改内存的函数啊!!

 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
我讲解一下c语言中动态分配内存的函数 PDF
下载积分:400
内容提示:
文档格式:PDF|
浏览次数:35|
上传日期: 21:21:05|
文档星级:
该用户还上传了这些文档
我讲解一下c语言中动态分配内存的函数 PDF.PDF
官方公共微信求关于两个关于c语言控制台函数的详解,谢谢
[问题点数:40分,结帖人h123456hxd]
求关于两个关于c语言控制台函数的详解,谢谢
[问题点数:40分,结帖人h123456hxd]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。C语言动态内存分配函数解析
- 热点新闻 - 成都腾睿工作室
目前位置: >
C语言动态内存分配函数解析
作者:admin网址:时间:点击:16
引言:对于指针,正确的分配动态
   内存的正式叫法是内存储器,以此来与外存储器区分开。物理上它安装在计算机内部,通常安装在主板上,所以称为内存。它的作用是供暂时存储处理器需要处理 的数据或处理后的结果,可见内存是计算机处理器的工作空间。它是处理器运行的程序和数据必须驻留于其中的一个临时存储区域,是计算机十分重要的部件。&
是十分重要的,本文将着重阐述动态分配函数malloc,calloc,realloc以及memset的用法。
  一、对于malloc,在终端输入 #:man& malloc可以知道函数原型是:
  Void *calloc(size_t& size) ,包含在库函数 stdlib.h中,作用是在内存的堆区分配一个大小为size的连续空间,如果分配内存成功,函数返回新分配内存的首地址,否则,返回,注意:鉴于上述这点,一般在写程序需要判断分配内存是否成功,如下程序语句:
  int& *p;
  p=(int *)malloc(sizeof(int));
  if(p!=NULL)
  .................................//需要执行的语句
  .........................//打印分配内存不成功出错信息
  通常造成内存分配失败的原因如下:
  1、 内存访问越界
  2、 所需连续的内存空间不足
  二、对于函数calloc用法大致与malloc相同,函数原型为:
  void *callo(size_t& num,size_t& size),作用是在内存中分配连续大小为num*size的空间,这一点在动态数组内存分配有所体现,返回值以及判断返回是否成功与上面相同,下面重点来讨论malloc与calloc区别:
  1、后者在返回指向内存的指针之前把它初始化为0。
  2、请求内存数量的方式不同。malloc的参数仅仅是需要分配的内存字节数;calloc的参数包括元素的数量和每个元素的字节数。
  为了说明第一点,请看如下程序:
  程序在第6行动态为指针p动态分配了内存, 经过gcc编译,运行结果如下:
  由图可以看出红色标记部分,并没有初始化为零,也就是说在这个单元存在随机数,这样程序在运行时可能会出错。将上面的程序用calloc来调用,程序如下:
  见上述程序第6行,用calloc来代替malloc分配内存单元,运行结果如下:
  可以看出在用calloc申请内存时将内存都初始化为0了。那么有没有用办法用malloc同时又将内存初始化为0呢?答案是有的,用menset可以实现这一功能将第一个程序做相应改动,程序如下:
  在第七行添加了语句menset(p,0,100),这条语句的意思是在内存单元p所指向的100个内存单元都赋值为0,相当与初始化内存。此时在运行此程序将不会再出现形如上述红色标记部分的结果。
   三、对于realloc(),函数原型是*void realloc(void& *ptr,size_t& size),改变ptr所指内存区域的大小为size长度,如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应 使用free()函数将内存块释放。有一点需要注意:当分配内存成功之后,应将原本的指针ptr=NULL,否则会形成野指针,可能造成系统崩溃。
  提示:不论是以上那种方式申请内存,在申请内存之后,最终都要用free释放空间,不然会造成内存泄漏。
您可能感兴趣查看: 115|回复: 4
C语言中字符串函数后隐藏的危险陷阱
C语言最强大的功能就是它的指针。有一句话说的很好:如果你爱编程,那么就会爱C语言,如果你爱C语言,你一定会爱指针。C语言的指针确实强大,随心所欲的修改内存给程序员提供了自由的发挥空间。但是C语言对缓冲区溢出不做检查,使得这种随心所欲的指针操作变得极度危险。内存泄漏,缓冲区溢出等问题往往是程序员们焦头烂额,深受其害。因为这些问题时隐时现,出现问题的地方也许跟问题一点关系都没有,非常难以调试。有时身经百战的程序员也会被这些内存错误搞的彻夜难免,从而通宵达旦的来找错误的根源。正是因为C指针的这种难以驾驭的性质,所以用C语言编写程序的时候一定要注意指针的应用技巧。
& && &&&C语言没有提供字符串类型,字符串以字符数组的形式出现,C标准库提供了一些操作字符串的函数,主要有:strcmp 字符串比较函数,strcpy 字符串拷贝函数, strlen 字符串测长函数, strcat字符串连接函数,sprintf格式化字符串拷贝函数等等。因为字符串就是以‘\0’结束的一段内存,这些函数实质上也就是操作内存的函数,所以避免不了的与指针打交道,使得这些函数充满了陷阱,如果这些函数使用不当,很有可能在程序中埋伏下危险的陷阱,使程序的稳定性遭受重创。下面我就字符串使用中一些常见的问题来进行举例说明。一. strcpy:极度危险的函数,一不小心就会中招,危险指数:四星& && &&&strcpy的原型是这样的: char *strcpy(char *dest, const char *src) 作为常见的字符串复制函数,C库中的实现是不安全的,因为它不做字符串的检查,以至于如果参数传入了非法指针,比如:src不是指向字符串的指针。后果就不堪设想,程序会一直复制,直到遇到‘\0’才结束,这样很有可能就会使得dest指向的内存区域缓冲区溢出,使得导致不程序相干的部分出现错误,这种错误也许就是致命的。所以使用这个函数一定确保第二个参数传入合法的指针。
#include &string.h&&&#include &stdlib.h&&&#include &stdio.h&&&&&char dest[5] = {'D'};&&char mydata[7] = {'m','y','d','a','t','a','\0'};&&&&int main(void)&&{&&& && &&&&&& && &&&char source[5];&&& && &&&char bound[5] = {'&','&','&','&','&'};&&&&& && &&&for (i = 0; i & 5; i++)&&& && && && && & source = 'S';&&&&& && &&&printf(&before strcopy, mydata is %s\n&, mydata);&&& && &&&strcpy(dest, source);&&& && &&&printf(&dest is %s\n&, dest);&&& && &&&printf(&after strcopy, mydata is %s\n&, mydata);&&&&}&&
& && &&&程序中定义了两个全局数组,我们知道C语言的全局变量要放在DATA段,而dest与mydata因为定义相连,所以其内存地址是相邻的。程序的目的是复制一个字符串到dest数组,而程序中忘了给source数组最后加上'\0'。所以source就不是一个字符串,用它传递给strcpy就会造成意想不到的后果。本程序中strcpy一直复制内存到dest,直到在遇到‘\0’, 这样就会多复制很多数据到dest,从而意外的覆盖mydata,甚至有时还会导致程序崩溃。在拷贝之前, mydata的数据是 &mydata&, 而在拷贝之后造成了意外的修改。
二. strcat 造成缓冲区溢出的隐形杀手,危险指数 三星
& && &&&strcat 是将一个字符串连接到另外一个字符串上,其函数原型为char *strcat(char *dest,char *src)。这个函数也很危险,因为C语言的实现也是不安全的,传入非法的指针有可能会造成程序的崩溃。首先保证两个指针都应该指向字符串,其次dest指针指向的空间要足以容的下src指向的字符串,否则会造成缓冲区溢出而破坏其他程序数据。
#include &string.h&&&#include &stdlib.h&&&#include &stdio.h&&&&&char dest[5] = {'D', '\0'};&&char mydata[7] = {'m','y','d','a','t','a','\0'};&&&&int main(void)&&{&&& && &&&&&& && &&&char source[5];&&& && &&&char bound[5] = {'&','&','&','&','&'};&&&&& && &&&for (i = 0; i & 4; i++)&&& && && && && & source = 'S';&&& && &&&source[4] = '\0';&&& && &&&printf(&before strcat, mydata is %s\n&, mydata);&&& && &&&strcat(dest, source);&&& && &&&printf(&dest is %s\n&, dest);&&& && &&&printf(&after strcat, mydata is %s\n&, mydata);&&&&}&&
& & 这个例子因为目标dest只有5个字节大小,并且数据占了一个字节,只剩下四个字节位置,而源数据字符串长度为4个字符加一个‘\0’有五个字节大小,所以会多出一个字节覆盖了mydata的数据,多出的‘\0’成为了mydata的第一个字节,导致调用strcat后输出mydata为空。
#include &string.h&&&#include &stdlib.h&&&#include &stdio.h&&&&&char dest[5] = {'D', 'D', 'D', 'D', 'D'};&&char mydata[7] = {'m','y','d','a','t','a','\0'};&&&&int main(void)&&{&&& && &&&&&& && &&&char source[5];&&& && &&&char bound[5] = {'&','&','&','&','&'};&&&&& && &&&for (i = 0; i & 4; i++)&&& && && && && & source = 'S';&&& && &&&source[4] = '\0';&&& && &&&printf(&before strcat, mydata is %s\n&, mydata);&&& && &&&strcat(dest, source);&&& && &&&printf(&dest is %s\n&, dest);&&& && &&&printf(&after strcat, mydata is %s\n&, mydata);&&&&}&&
& && &&&这个例子中,dest不是字符串(没有‘\0’结尾),导致strcat从地址dest处开始找'\0',找到'\0'后并在此地址上复制source的数据,在本程序中就将source连接到了mydata后面,导致mydata变成了“mydataSSSS”,这样也破坏了程序无关的数据,本程序中还好是破坏的DATA中的数据,如果是其他的数据那么后果不不仅仅是数据改变这么简单了。
三.&&strlen 很多malloc函数缓冲区溢出问题的始作俑者 危险指数 二星
& && &&&strlen是字符串求长函数,但是它求出的长度不包括‘\0’,所以在用malloc分配内存的时候,很容易少分配一个字节,就这小小的一个字节就会造成缓冲区溢出,我们知道malloc分配的内存区域是有一个头的,这样就有可能破坏其他malloc的头使得内存释放失败,带来一系列连锁反映。因为malloc函数的实现与系统有关,这个不好用程序模拟,但是这种情况确实存在。因此如果用strlen求字符串长度用于malloc一定要记住要加1。
四.&&sprintf 同样可以造成缓冲区溢出,危险指数 一星
& && &&&sprintf是格式化字符拷贝函数,函数原型是int sprintf( char *buffer, const char *format, … ) 。这个函数的实现也是不安全的,使用这个函数要确保buffer足够大,否则这个函数在不做任何提示的情况下就将buffer溢出,这个函数虽然返回复制的字节数,可以通过这个检查复制了多少个字节,以确定是否缓冲区溢出。但这种亡羊补牢的做法其实没有实际意义。缓冲区溢出的错误已经发生也许会是程序崩溃,检测的时间也许都没有,就算有检测时间,也只是用于提示程序的BUG,在正式的程序中没有多大用处。
#include &string.h&&&#include &stdlib.h&&&#include &stdio.h&&&&&char dest[2] = {'D'};&&char mydata[7] = {'m','y','d','a','t','a','\0'};&&&&int main(void)&&{&&& && &&&&&& && &&&char source[5];&&& && &&&char bound[5] = {'&','&','&','&','&'};&&&&& && &&&for (i = 0; i & 4; i++)&&& && && && && & source = 'S';&&& && &&&source[4] = '\0';&&& && &&&printf(&before sprintf, mydata is %s\n&, mydata);&&& && &&&sprintf(dest, &%s&, source);&&& && &&&printf(&dest is %s\n&, dest);&&& && &&&printf(&after sprintf, mydata is %s\n&, mydata);&&&&}&&
& && && &这个例子中,目标缓冲区只有两个字节的大小,而源字符串却是五个字节,sprintf在不进行任何提示的情况下,默默的覆盖了mydata的数据。
总结& && &&&
& && &&&总上所述,C语言字符串操作函数一般都不对参数做检查,需要调用者确保参数的合法性。如果传入不正确的参数,就会造成缓冲区溢出。轻则数据被修改,重则程序崩溃。最郁闷的是影响到程序中不相关的部分。我前面举的例子都很简单,很容易一眼看出问题的所在,但是大型程序就不会这么简单了,这些错误就是致命的。所以使用C语言的字符串函数时一定要养成良好的习惯,自己检查参数的合法性,然后再调用。目前C语言中这些字符串操作函数都有一些安全的版本就是带n的系列,比如:strncpy,strncat,snprintf。这些函数规定了源字符串的大小,对缓冲区溢出的预防有一定的作用,比如:snprintf,其函数原型是int snprintf(char *str, size_t size, const char *format, ...) 第二个参数size,可以保证复制size个字节,如果要复制的字符串大于size就会截短,从而保证str不会溢出。程序中尽量使用这些安全的版本。良好的习惯是一个程序稳定与健壮的保证,而良好的习惯都是使用这些常用的函数养成的,所以一定要主要这些字符串函数的使用。
楼主知识怎么知道这么多啊
用memset&&memcpy 这些就不会出现上面的问题啦,效率还更高呢。不过就是不够灵活而已。
发表于 4&天前
发表于 4&天前
不擅长指针求大神,关于c语言删除函数_百度知道
求大神,关于c语言删除函数
void deletel(struct st *head){stud *p,*q;
char c,N[10];char Num[15];p=p=(stud *)malloc(sizeof(stud));
q=(stud *)malloc(sizeof(stud));q=p-&p=if(p-&next!=NULL){printf(&1--按姓名删除,2--按学号删除\n&);printf(&你的选择是\n&);
scanf(&%d&,&m);getchar();switch(m){case 1: printf(&你要删除人的姓名为\n&);
gets(N);while((p!=NULL)&&(strcmp(p-&name,N)!=0)){p=p-&}case 2:
printf(&你要删除的人的学号为\n&);
gets(Num);while((p!=NULL)&&(strcmp(p-&num,Num)!=0))
}default :printf(&输入错误:\n&);}}
q=p-& if(q==NULL){printf(&未找到指点节点,没有执行删除\n&);}printf(&你要删除人的信息为\n&);printf(&学号
电话\n&);
printf(&%-14s%-10s%-8s%-12s%-8d%-15s\n&,p-&num,p-&name,p-&sex,p-&born,p-&age,p-&tel);printf(&quot憨户封鞠莩角凤携脯毛;你确定删除此人,y——删除,n——不删除\n&);c=getchar();if(c=='y'){p-&next=q-&free(q);}}
1. 函数开始的时候这两句话没有意义
p=(stud *)malloc(sizeof(stud));
q=(stud *)malloc(sizeof(stud));你只是憨户封鞠莩角凤携脯毛用了这两个指针,为它们分配空间一是没必要,二是内存会泄露2. 看你的代码应该是有头结点的链表,搜索的时候p=p初始化为了head,指向了头结点,搜索的时候应该从p-&next开始,而你用的while((p!=NULL)&&(strcmp(p-&name,N)!=0)),应该用p-&next!=NULL。而且后面删除的时候也删除的是p-&next,所以比较的话也应该用p-&next:strcmp(p-&next-&name,N)
其他类似问题
按默认排序
其他1条回答
楼上是正解,采纳他的第二条建议可解决问题;采用第一条可提高程序性能。
您可能关注的推广回答者:
c语言的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁}

我要回帖

更多关于 c语言函数调用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信