精华内容
下载资源
问答
  • 内存泄露越界
    2020-10-23 00:54:07

    内存泄露与越界是C/C++世界两大灾难。关于内存泄露,因为服务器可以用mempool,除了不需要delete以外还可以避免内存碎片提高运行速度,所以对于如何应付内存泄露我没有特别的心得。但是对于如何应对内存越界,有一些小经验。例如memcpy函数void * memcpy ( void * destination, const void * source, size_t num );就是容易发生越界的一个经典函数,刚开始做后台的几年里面因为这个函数出现的内存问题次数不少,但是后来发现可以用C++的方法来改造它。总结了一下实际memcpy函数使用主要有两种场景,一是对于结构体的拷贝,二是对于char类型的数组的拷贝。先说结构体的拷贝,对于Struct A {....};A a, b;如果要把b的内容拷贝到a,有两种方法:memcpy(&a, &b, sizeof(a));或者:a = b;前面一种方法容易出错,改成后面一种。(a=b这种赋值拷贝的方法在C里面也是可以的,不能算是C++的改进,感谢miloyip指正)。memcpy函数需要使用的第二种场景,是将结构体拷贝到一个buffer中,类似这样:char buff[N]; memcpy(buff, &a, sizeof(a));这个当然也不是类型安全的,容易出问题,用C++的方法可以这样改造:template<size_t N, class A>
    void memcpy_safe(char (&arr)[N], const A* p)
    {
        static_assert(sizeof(A) <= N, "error blabla");
        ::memcpy(arr, p, sizeof(A));
    }
    然后调用memcpy_safe(buff, &a)就安全了。当然这里有个问题,就是拷贝的目标地址buff,必须声明为char buff[N]的形式,不能直接用char buff = new char[N]的形式,需要动态创建buffer的时候可以将buff封装在结构体里面,如:struct buffer_type { ...; size_t length; char buff[MAX_LEN]; }; 然后buffer_type* p = new buffer_type; memcpy_safe(p->buff, &a); 我们后台代码中类似用法已经全部改掉了。同理把snprintf之类的函数也全部用C++的方法封一遍,常见的内存问题都解决了。这些年我带的项目运营事故越来越少了,慢慢地在老大心中形成了一种口碑。
    作者:飞鼠明天做窝
    链接:https://www.zhihu.com/question/28834538/answer/434460812

    个人总结;

    可以用内存复用的方式,不用了不用delete,下次用的时候重新启用

    更多相关内容
  • 面一家音视频开发公司c++岗位时候问到了这个内存泄露相关的问题,问的是在平时碰到了内存泄露相关的问题吗? 1.忘记free啊 2.循环里使用了malloc,循环写死内存用光了啊 3.数组或指针访问越界啊 4.向系统申请分配...

    面一家音视频开发公司c++岗位时候问到了这个内存泄露相关的问题,问的是在平时碰到了内存泄露相关的问题吗?

    1.忘记free啊
    2.循环里使用了malloc,循环写死内存用光了啊
    3.数组访问越界或指针非法访问啊
    4.向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。
    5.在函数中调用构造函数使用了new,却没有释放,虽然最终系统会进行回收,但还是会造成内存的泄露,应该使用析构函数进行释放的操作。
    等等…

    1.内存泄露

    1.什么是内存泄露?
    内存泄露是指程序中已动态分配的堆内存因为某种原因未释放或无法释放,造成内存空间的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

    2.内存泄露的分类?
    (1)常发性内存泄露:发生泄露的代码会被多次执行到
    (2)偶发性内存泄露:发生泄露的代码在某些环境或操作下才会发生
    (3)一次性内存泄露:只会被执行一次
    (4)隐式内存泄露:程序在运行过程中不断分配内存,直达结束后才释放。严格来说这不算内存泄露,但是服务器运行时间很长,可能会耗尽所有内存

    实例:
    当运行下面的Test函数会有什么样的后果?

    void GetMemory(char **p,int num)
    {
    	*p = (char *)malloc(num);	
    } 
    
    void Test(void)
    {
    	char *str = NULL;
    	GetMemory(&str,100);
    	strcpy(str,"hello");
    	printf("%s\n",str);
    }
    

    答案:内存泄露
    解读:调用malloc()申请内存空间, 使用完毕之后没有free()释放内存空间并使得指针指向NULL

    2.内存溢出

    1.什么是内存溢出?
    内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于系统能提供的最大内存。此时程序无法运行,系统提示内存溢出。有时会自动关闭软件。

    2.造成内存溢出的原因?
    (1)内存泄露的堆积最终导致内存溢出
    (2)需要保存多个耗用内存过大的对象或者加载单个超大对象时,其大小超过了当前的可用内存空间

    3.内存溢出与内存越界的区别?
    (1)内存溢出:要求分配的内存超过了系统所能够给予的,于是产生溢出
    (2)内存越界:向系统申请了一块内存,而在使用的时候超过了申请的范围,常见的如数组访问越界

    3.堆栈溢出

    堆栈溢出一般包括堆内存溢出栈内存溢出,两者都属于缓冲区溢出

    (1)堆内存溢出:可能是堆的尺寸设置的太小、动态申请的内存没有释放等

    (2)栈内存溢出:可能是堆的尺寸设置的太小、递归层次太深、函数调用层次过深、分配了过大的局部变量等

    4.野指针

    看下面第一个实例:
    当运行下面的Test函数会有什么样的后果?

    char *GetMemory(void)
    {
    	char p[] = "hello world";
    	return p;
    }
    
    void Test(void)
    {
    	char *str = NULL;
    	str = GetMemory();
    	printf("%s\n",str);
    }
    

    答案:打印野指针内容,可能是乱码
    解读:GetMemory()返回的是栈内存的指针,但是函数执行完完,该栈上内存就会被释放,该指针地址不是NULL,称为野指针,新内容不可知。

    再看一个实例:
    当运行下面的Test函数会有什么样的后果?

    void test()
    {
    	char *str = (char *)malloc(100);
    	strcpy(str,"hello");
    	free(str);
    	if(str != NULL)
    	{
    		strcpy(str,"world");
    		printf("%s\n",str);
    	}
    }
    

    答案:篡改堆区野指针指向的内容,后果难以预料,非常危险
    解读:
    (1)free(str)之后,str称为野指针,没有设置为NULL,而 if(str != NULL) 语句不能组织篡改操作
    (2)野指针不是NULL指针,是指向被释放的或者访问受限的内存的指针

    造成野指针的原因:
    (1)指针变量没有初始化,任何刚创建的指针不会自动生成为NULL
    (2)指针被free或者delete之后没有设置为NULL
    (3)指针操作超越了变量的作用范围,比如要返回指向栈内存的指针或引用,因为栈内存在函数结束后就被释放了

    展开全文
  • 内存泄漏 百度百科上的定义:内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 一看定义,坑好像更多...

    内存泄漏

    百度百科上的定义:内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

    一看定义,坑好像更多了,动态分配,堆内存是什么?
    某种原因包含哪种原因?
    未释放我能理解,无法释放是什么时候
    看后果很严重,运行速度减慢!系统崩溃!那么内存究竟为什么这么强??

    危害举了一个例子,比如服务器应用软件,需要长时间的运行,如果没有有效的内存管理,每次处理客户发来的信息都没有释放内存,产生内存泄漏,那么这样就会影响服务器的性能,引起整个系统的崩溃。

    它是拿C语言做的例子,看完危害,我们再来看看百度百科的泄露原因:

    从变量存在的时间来分类,分为静态存储变量和动态存储变量
    静态存储变量:程序运行期间分配了固定存储空间的变量
    动态存储变量:程序运行期间根据实际需要动态地分配存储空间的变量。
    所以它们的区别就在于,一个是一开始固定分配好了,一个是根据实际需要,你要多少我分配给你多少。感觉动态分配很棒,他怎么实现的呢?

    内存中供用户使用的区域:程序存储区,静态存储区,动态存储区
    程序用的数据呆在静态存储区和动态存储区
    静态存储区数据在程序的开始就分配好内存区,在整个程序执行过程中它们所占的存储单元是固定的,在程序结束时就释放(真省心啊),因此静态存储区数据一般为全局变量。全局变量的坑等下补,我们把全局变量和静态变量,静态存储区的关系捋一下

    动态存储区数据则是在程序执行过程中根据需要动态分配和动态释放的存储单元(分配了要释放呀!)动态存储区数据有三类函数形参变量(三类函数时哪三类)、局部变量和函数调用时的现场保护与返回地址。现场保护又是什么。。

    程序中动态分配的存储空间,在程序执行完毕后需要进行释放。
    没有释放动态分配的存储空间而造成内存泄漏,是使用动态存储变量的主要问题。
    一般情况下,开发人员使用系统提供的内存管理基本函数,如malloc、recalloc、calloc、free等,完成动态存储变量存储空间的分配和释放。

    无论是C还是C++程序,运行时候的变量主要有三种分配方式:堆分配、栈分配、全局和静态内存分配。内存泄漏主要是发生在堆内存分配方式中,即“配置了内存后,所有指向该内存的指针都遗失了”,若缺乏语言这样的垃圾回收机制,这样的内存片就无法归还系统。

    总结一下,内存泄露,是指程序在申请内存后(申请这个用词还是形象呀),无法释放或未释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
    内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。
    举个例子,就像你申请把一个物品装在保险柜里,你用它的时候给它分配了一个保险柜,可是用完了没有把你的保险柜收回,你走就走了,可是记不了保险柜的地址,再也找不到这个保险柜了,你觉得没问题,我有好多保险柜呢,可是如果这个问题一直发生,你的保险柜会全部用光的。
    哈哈哈,对C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针。你这个没有对象的野指针哈哈哈哈哈。这句话怎么理解呢,我决定去看看野指针的定义!

    野指针

    百度百科上,野指针的定义:野指针指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。需对指针进行初始化

    引用百度百科上的野指针介绍,讲的还是蛮清楚的

    为什么会出现野指针:

    指针变量未初始化
    任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存(int *p = &a, 这就是指向合法的内存了。)。如果没有初始化,编译器会报错“ ‘point’ may be uninitializedin the function ”。
    指针释放后未置空
    有时指针在free或delete后未赋值 NULL,便会使人以为是合法的。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。
    看到2我明白了,上面说的:对C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针。我觉得不太准确,内存泄漏说的是为对象申请的内存未被释放,野指针说的是指向已被删除的或者未申请受限访问内存的指针。怎么能说内存泄漏俗称野指针呢?这就像说保险柜没清理(内存泄漏)和指向特殊保险柜的指示牌(野指针)是一回事一样。
    3.指针操作超越变量作用域
    就是在你超过作用域后,内存已经释放,这时指向那个被释放的内存的指针就是野指针,你却还调用,这样不好。这个例子就是原因

    class A {
    public:
      void Func(void){ cout << “Func of class A” << endl; }
    };
    class B {
    public:
      A *p;
      void Test(void) {
        A a;
        p = &a; // 注意 的生命期 ,只在这个函数Test中,而不是整个class B
      }
      void Test1() {
      p->Func(); // p 是“野指针”
      }
    };


    申请内存是怎么一回事?

    在C++中,进行堆内存管理的是new和delete
    对应C中的malloc和free
    但是 malloc 和 free 是函数,而new 和 delete 是运算符
    这篇博客讲C++和C的内存管理挺不错的

    总结一下,
    我们谈到了内存泄漏是什么,野指针是什么及它的成因
    C++和C的内存管理

    其实留下了一堆坑,比如堆内存,还有需要单独开一篇文章来说C和C++的内存管理,我认为这是这两个编程语言比较重要的特性。
    --------------------- 
    作者:ydycef 
    来源:CSDN 
    原文:https://blog.csdn.net/sinat_41613352/article/details/84559681 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • 内存问题一直以来都是C/C++开发中比较麻烦的问题,总的来讲,可以分成内存碎片、内存泄漏和内存越界这几类其中,以内存越界最为复杂,而且难以定位。下面我们将通过技术手段逐一分析并解决这三个问题。 一、操作...

           内存问题一直以来都是C/C++开发中比较麻烦的问题,总的来讲,可以分成内存碎片、内存泄漏和内存越界这几类其中,以内存越界最为复杂,而且难以定位。下面我们将通过技术手段逐一分析并解决这三个问题。

    一、操作系统的内存管理

    进程的虚拟内存空间是地址是连续的,整个内存空间以页为单位进行划分,并不是每个页当前都映射了物理地址(commited),应用程序通过操作系统提供的API对内存进行管理,以页为单位,将虚拟内存地址映射到物理地址或者解除虚拟地址和物理地址的映射,某些情况下操作系统也会自动进行这个过程:例如当物理内存不足时,会根据一定的策略将部分虚拟空间的数据保存到硬盘上,同时解除虚拟空间和物理地址的映射,把空出来的物理地址映射到当前cpu需要访问的虚拟空间(拆东墙补西墙)。

    一、内存碎片

            当应用程序通过操作系统提供的API动态的申请内存和归还内存,那么难以避免的就会造成当前已分配的内存在进程中占用着不连续的虚拟空间,反过来,不被应用程序占用的空闲内存空间也是不连续的,那么即便这些空闲内存的总量大于下次应用程序申请的空间大小,因为不连续,所以也无法成功申请到。空闲内存不连续的问题越严重(不连续的内存快越多,每块内存越小),分配不成功的概率就越大。

           我们通过以下几个技术手段解决这个问题:

          1、 建立小内存池机制,相同大小或者大小接近的内存都放到同一个内存池,这样从内存池的每个内存块之间浪费的内存会非常小或者没有浪费。

          2、内存池向系统申请内存时都以页为单位进行申请大块内存(Block),内存池对外分配内存也以优先使用使用率最高的Block,这样会有更高的概率将整个Block归还系统。

    二、内存泄漏

          内存泄漏产生的原因比较简单明确,就是申请的内存已经不需要再次被使用了,但是并没有归还给内存分配器(管理器)或者系统。正确的使用智能指针可以有效的避免内存泄漏的发生,这是推荐的方式。我们下面介绍另外一种在X86下解决内存泄漏的方式。

           我们在每次进行内存分配的时候将调用的堆栈记录下来,并且和分配的内存块进行关联,这样,分配的每一块内存都有一个明确的来源,这样我们可以随时统计哪些地方分配了多少内存(内存快照)。我们可以在需要时生成一个内存快照,通过对比内存快照可以确定这段时间内哪些地方分配或者释放了多少内存。

    三、内存越界

           内存越界是比较难以定位,并且也是非常危险的一个问题。内存越界通常发生的场景有(不限于以下):

           1、读写超出内存的有效范围,例如数组下标越界,指针加减运算错误

           2、已释放的内存,其指针仍然被某些地方非法持有(野指针),并且进行了读或者写

           内存越界读产生的危险总体而言要小于越界写。因为数据读错了,很大概率会立刻暴露问题,比较容易定位,但是越界写的话,很有可能会在后续某个完全不相干的位置或者时间里出现问题,这时已经很难再找回之前写坏数据的现场了。下面我们讨论一种定位内存越界写的方案。

           内存越界写主要的问题是往往写的时候没有引发异常,如果我们能在越界写的时候让程序抛出异常,那么这个问题基本就定位了。为此,我们可以令内存分配器每次分配都返回一个永远不重复的地址,这个地址指向的内存前面和后面的一页或者几页的地址空间都是没有映射到物理内存的,那么当对这块内存的读写超出边界的时候就会触发暴力读写的异常。同样,当这块内存被释放以后,我们将这块内存所指向的虚拟地址和物理地址的映射解除,那么后续尝试对这个地址进行读写的时候也会触发暴力读写的异常,这样我们就可以快速定位问题所在。

    以下是完整的内存解决方案:

    https://github.com/daphnis-kau/XMemory

    展开全文
  • 内存泄漏检测和内存越界检测

    千次阅读 2019-05-17 14:13:39
    本程序为内存泄漏和内存越界检测。本文及程序为原创,转发请标注littlezls原创。 欢迎大家相互交流学习。 1. 说明 作为一个编程人员,或许你会需要下面三个问题: 1.由于代码量大,项目复杂, 用系统函数malloc,...
  • 内存泄漏指的是程序中有申请内存的过程,但在程序结束之后,始终没有或者无法释放占有的内存的则称为内存泄漏,单次的内存泄漏可能用户并不会察觉,但是累积的内存泄漏将会十分可怕,无论内存的大小,终会被耗光。...
  • 在用C++做底层驱动时,经常会遇到内存不足的警告,往往是因为内存出现溢出、泄露或者越界等原因。 内存溢出(out of memory) 是指程序在申请内存时,没有足够的内存空间供其使用。 内存泄漏(memory leak) 是指...
  • 面试题(c/c++)

    2018-11-01 19:15:27
    https://blog.csdn.net/u013162035/article/details/78308140 ... 目录 1,C++中指针引用的区别 1.1int *ptr=(int *)(&a+1) 2.堆栈的区别 3.变量的声明定义有什么区别 4.s...
  • Malloc内存泄露和内存越界问题的研究 ------内存跟踪与检测篇 1.引言 熟悉c语言的人都知道,内存泄露,特别是内存越界是软件界非常棘手,甚至防不胜防的问题。由于这种问题一般为概率问题,时而出现时而不出现,...
  • 它们都可用于申请动态内存和释放内存; 2)new 返回指定类型的指针,并且可以自动计算所需要大小。而 malloc 则必须要由程序员计算字节数,并且在返回后强行转换为实际类型的指针; 3)new/delete在对象创建的同时...
  • c++的newdelete操作,可以让我们在程序运行中动态的开辟内存空间,但是我们知道,一旦处理不好就会造成内存泄漏。一直有一个疑问,c++为防止(或者说检测)指针越界做了哪些工作? struct _CrtMemBlockHeader _...
  • 内存溢出 out of memory,...内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。 memory leak会最终会导...
  • C++ 不试用工具如何检测内存泄漏指针越界等问题?  简单的想法是修改共享库,以达到控制内存操作功能,如malloc/free等内存管理函数、memcpy/strcpy/memset等内存读取函数指针运算等,自主管理内存,查看异常。...
  • c++的newdelete操作,可以让我们在程序运行中动态的开辟内存空间,但是我们知道,一旦处理不好就会造成内存泄漏。一直有一个疑问,c++为防止(或者说检测)指针越界做了哪些工作? struct _CrtMemBlockHeader _...
  • 文章目录内存溢出内存泄露内存越界栈溢出 内存溢出 内存泄露 内存越界 栈溢出
  • 游戏服务器开发仍然使用c++ 作为主语言,但是大多结合动态脚本技术,一方面规避了野指针和内存泄露,一方面获得了开发效率扩展性的红利。今天主要说说在使用c++过程中,如何避免解决野指针和内存泄漏问题。 野...
  • 指针和内存泄露是令开发人员畏惧的,但反过来如果掌握了这方面的基础,那同样可成为开发人员的强大的工具。本文的主要内容l导致内存破坏的指针操作类型l在使用动态内存分配时必须考虑的检查点l导致内存泄露的场景1、...
  • 内存泄露:分配了内存而没有释放,逐渐耗尽内存资源,导致系统崩溃内存越界: 打个比方 就是你有一个500ml的水瓶,然后你倒在瓶里的水大于500ml 那个多余的就会流出来... 1.原理分析经常有些新C++程序员问:C++的...
  • 关于数组越界内存泄漏)的那点事儿(C语言)   数组越界在C语言是一个很常见的问题,但是也正是因为它很常见,有时候也会出现一些不可思议,难以理解的情况,就像下面这样。 情形如下: 如果难以理解,我们来...
  • =================================================================内存越界:何谓内存访问越界,简单的说,你向系统申请了一块内存,在使用这块内存的时候,超出了你申请的范围。内存越界使用,这样的错误引起的...
  • 指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具。 本文将与您分享开发人员在开始使用指针来编程前应该知道的秘密。本文内容...
  • ================================================================内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的...
  • 在写C/C++程序时,要小心内存泄漏内存越界访问,但最粗心的也就是这一块;在程序运行过程中,最担心的也就是突然core掉,或程序占用完内存。此时要么DBG产生的core文件,要么是查看日志再对照源代码,假如此时你的...
  • 内存泄露 内存泄漏(memory leak)是应用程序分配某段内存后,由于疏忽或者错误,失去了对该段内存的控制,因而造成了内存的浪费。 或者可以说向系统申请分配内存进行使用(new),但是用完后不归还(delete),导致...
  • 检测内存泄漏 其他内存问题 memcheck 工具的常用选型 其他选项 附录 其他类似工具 实例分析: 03. 使用未初始化的内存 04. 使用野指针 05. 动态内存越界访问 06. 分配空间后没有释放 07. 不匹配使用delete...
  • 内存泄漏 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 内存越界 你想系统申请一块内存,在使用的...
  • 摘要:该文从指针在C语言中的作用入题,介绍了指针使用过程中常见的几种错误,并提出了改进...数组越界中图分类号:TP311文献标识码:A文章编号:1009-3044(2011)13-3077-04计算机内存中每个存储单元都有其存储地...
  • 定义 内存泄露(memory lock)是指由于疏忽或错误... 一般常说的内存泄露是指堆内存的泄露,堆是动态分配内存的,并且可以分配使用很大的内存,使用不好会产生内存泄露,使用不好会产生内存泄露。频繁的使用mallo...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,871
精华内容 7,148
关键字:

内存泄露和指针越界