内存损坏问题的示例及分析

简介: 原文以示例代码系统的讲述了三种内存损坏的情况: 全局内存、栈损坏及堆损坏, 以及它们产生的原因。粗略整理如下。Global Memory Corruption即全局变量的内存使用出了问题,主要还是越界。

原文以示例代码系统的讲述了三种内存损坏的情况: 全局内存、栈损坏及堆损坏, 以及它们产生的原因。粗略整理如下。


Global Memory Corruption

即全局变量的内存使用出了问题,主要还是越界。如下代码:

#include <stdio.h>
#define MAX 6
int arrdata[MAX];
int endval;
int main()
{
   int i = 0;
   endval = 12;
   for (i = MAX; (endval) && (i >= 0) ; i--, endval--)
   {
      arrdata[i] = endval * endval;
   }

   printf("Values are \n");
   for (i = 0; i < MAX; i++)
   {
      printf("\t %d\n", arrdata[i]);
   }
   return 0;
}


编译执行,输出的结果是:

Values are
19044
19321
19600
19881
20164
20449


走查代码,你可以发现第一个循环里i的初值是MAX, 应该是MAX-1。 正是这个越界,改写了endval的值。

那个全局变量在内存里是邻居(译注:在我的Mac OS上的输出结果):

(gdb) p &endval
$2 = (int *) 0x100001038
(gdb) p &arrdata
$3 = (int (*)[6]) 0x100001020


所以arrdat[MAX]的赋值操作,实际变成了对endval的赋值。


这样的破坏操作可以概括为两种:

  •  数组越界,向上或向下(负值).
  •  通过指针访问了错误的地址。


Stack Corruption

在*nix系的系统里,Stack会用来存储局部变量, 函数参数以及返回值。栈损坏常常导致未知的行为及崩溃。


栈损坏有两种情况:

  • 内存越界操作。
  • 栈溢出(stack overflow)。


内存越界

越界的情况和之前相似,只是发生在了栈存储的数据上。比如下面的代码 :

#include <stdio.h>
#include <string.h>
#define LEN 6

void cpyPrint(char *str)
{
   char aBuf[LEN];
   strcpy(aBuf, str);

   printf("String is %s\n", aBuf);
}

int main()
{
   char *aStr = "MyLinux";

   cpyPrint(aStr);

   return 0;
}


编译执行就会崩溃。下面是在我的Mac OS上的结果:

(gdb) r
Starting program: /Volumes/Development/Project/Testing/stackcorrupt
Reading symbols for shared libraries +.............................. done

Program received signal SIGABRT, Aborted.
0x00007fff88815d46 in __kill ()
(gdb) bt
#0  0x00007fff88815d46 in __kill ()
#1  0x00007fff8602d053 in __abort ()
#2  0x00007fff85fee74d in __chk_fail ()
#3  0x00007fff85feea1f in __strcpy_chk ()
#4  0x0000000100000ea6 in cpyPrint (str=0x100000f3e "MyLinux") at stackcorrupt.c:8
#5  0x0000000100000ef3 in main () at stackcorrupt.c:17


原因在cpyPrint函数中的局部变量大小为6,却要放进去8个字符(包括一个结束符)。


栈溢出

下面是栈溢出问题的示例代码:

#include <stdio.h>
int recur(long int var)
{
   if (var > 0)
   {
       recur (var--);
   }

   printf("the var is %ld\n", var);
   return var;
}

int main()
{
   recur (3000);
   return 0;
}


这段代码什么时候崩,还要看在运行的系统里的栈大小的设置,可以使用下面的指令直接查到:

$ulimit -s

默认情况下会是8192 (KBytes)。


Heap Corruption


出现堆错误,会报臭名昭著的Segment Fault错误。产生的原因有三种:

  • 尝试向已经释放的内存写入数据。
  • 越界操作 (的确是最常见的原因)。
  • 尝试向尚未分配的内存写入数据。


下面是一个示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{
   int *pData = NULL;
   int num = 12;
   pData = (int*) malloc (num * sizeof (int));
   //...do stuff use the memory
   free(pData);

   pData[0] = -1;
   pData = (int*) malloc (num * sizeof (int));
   //...do stuff use the memory
   free(pData);
   return 0;
}


要想排查内存问题,首选工具自然是Valgrind了,不多做介绍了。


原因链接: http://mylinuxbook.com/memory-corruption-in-linux-programming/

 


相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
1月前
|
缓存 Java
Java中循环创建String对象的内存管理分析
Java中循环创建String对象的内存管理分析
25 2
|
6天前
|
存储 Arthas 监控
JVM工作原理与实战(三十):堆内存状况的对比分析
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了堆内存状况的对比分析、产生内存溢出的原因等内容。
12 0
|
8天前
|
缓存 Linux
linux性能分析之内存分析(free,vmstat,top,ps,pmap等工具使用介绍)
这些工具可以帮助你监视系统的内存使用情况、识别内存泄漏、找到高内存消耗的进程等。根据具体的问题和需求,你可以选择使用其中一个或多个工具来进行内存性能分析。注意,内存分析通常需要综合考虑多个指标和工具的输出,以便更好地理解系统的行为并采取相应的优化措施。
28 6
|
11天前
|
机器学习/深度学习 分布式计算 数据处理
Spark是一个基于内存的通用数据处理引擎,可以进行大规模数据处理和分析
【5月更文挑战第2天】Spark是一个基于内存的通用数据处理引擎,可以进行大规模数据处理和分析
23 3
|
13天前
|
监控 算法 测试技术
【Go语言专栏】Go语言的性能优化与内存分析
【4月更文挑战第30天】本文探讨了Go语言的性能优化策略和内存分析方法。性能优化原则包括基准测试、分析瓶颈、避免过早优化和持续监控。优化策略涉及减少内存分配、避免内存逃逸、利用并发、优化算法和数据结构以及减少系统调用。内存分析借助于Go的`pprof`工具、内存分配跟踪和第三方工具,以发现内存泄漏和管理问题。通过这些方法,开发者能提升Go程序效率和资源利用率。
|
16天前
|
缓存 Java Android开发
安卓开发中的内存泄漏分析与优化策略
【4月更文挑战第27天】 在移动应用开发领域,性能优化始终是提升用户体验的关键因素之一。特别是对于安卓平台,由于设备的硬件配置差异较大,良好的内存管理对于保证应用流畅运行尤为重要。本文将深入探讨安卓开发中常见的内存泄漏问题,并提供一系列检测和解决内存泄漏的实用策略。通过对工具的使用、代码实践以及系统架构设计的多维度分析,旨在帮助开发者有效避免和处理内存泄漏,确保应用性能稳定。
|
20天前
|
Java
【Java基础】面向对象和内存分析
【Java基础】面向对象和内存分析
17 0
|
20天前
|
存储 Java Shell
Android系统 实现低内存白名单防LMK原理分析
Android系统 实现低内存白名单防LMK原理分析
33 0
|
1月前
|
存储 程序员 编译器
c++面向对象概述、内存分析、引用、函数
c++面向对象概述、内存分析、引用、函数
|
2月前
|
SQL 运维 NoSQL
【Redis 故障排查】「连接失败问题排查和解决」带你总体分析CPU及内存的使用率高问题排查指南及方案
【Redis 故障排查】「连接失败问题排查和解决」带你总体分析CPU及内存的使用率高问题排查指南及方案
41 0