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

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

粗略整理例如以下。

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/

时间: 2024-08-02 15:11:28

内存损坏问题的演示样例及分析的相关文章

最简单的视音频播放演示样例4:Direct3D播放RGB(通过Texture)

===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频播放演示样例2:GDI播放YUV, RGB 最简单的视音频播放演示样例3:Direct3D播放YUV,RGB(通过Surface) 最简单的视音频播放演示样例4:Direct3D播放RGB(通过Texture) 最简单的视音频播放演示样例5:OpenGL播放RGB/YUV 最简单的视音频播放演示样例

C编程规范, 演示样例代码。

/*************************************************************** *Copyright (c) 2014,TianYuan *All rights reserved. * *文件名: standard.h *文件标识: 编程规范演示样例代码 * *当前版本号:V1.0 *作者:wuyq *完毕日期:20140709 * *改动记录1: //改动历史记录.包含改动日期.版本号号.改动人及改动内容等 *改动日期 版本号号 改动人 改动内

Java线程演示样例 - 继承Thread类和实现Runnable接口

进程(Process)和线程(Thread)是程序执行的两个基本单元. Java并发编程很多其它的是和线程相关. 进程 进程是一个独立的执行单元,可将其视为一个程序或应用.然而,一个程序内部同事还包括多个进程. Java执行时环境就是一个单独的进程,在它内部还包括了作为进程的各种类和程序. 线程 能够将线程看做轻量级的进程. 线程存在于进程其中,须要的资源开销较小.同一进程中的线程共享进程的资源. Java多线程 每个Java引用都仅仅要有一个线程 - 主线程(main thread).尽管后台

关于栈及其应用演示样例

转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/30802249 作者:小马 作为一种经常使用的数据结构, 了解栈对于算法的学习是很必要的. 栈有先进后出的特点,栈底指向数据表中的第一个元素.栈顶指向最后一个元素的下一个位置. 例如以下图所看到的: 栈和线性表类似.也是有两种存储结构.分别为顺序结构和链式结构. 大部分情况下,栈使用前者.这和它的使用场景有关.由于通常情况下我们不会对栈进行频繁地.随机地插入,删除操作.以下是我用顺

JBoss 系列一 O O:Maven jBPM 6 集成演示样例

概述 jBPM 6 中底层架构基于 Maven,所以我们能够非常easy的进行 Maven jBPM 6 集成演示样例,本文分三个部分: 基本原理介绍 Maven jBPM 6 集成 jBPM 6 中使用 Maven 特性实时监听server端的更新 基本原理介绍 例如以下图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva3lsaW5zb29uZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/diss

最简单的视音频播放演示样例7:SDL2播放RGB/YUV

===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频播放演示样例2:GDI播放YUV, RGB 最简单的视音频播放演示样例3:Direct3D播放YUV,RGB(通过Surface) 最简单的视音频播放演示样例4:Direct3D播放RGB(通过Texture) 最简单的视音频播放演示样例5:OpenGL播放RGB/YUV 最简单的视音频播放演示样例

PHPCMS中GET标签概述、 get 标签语法、get 标签创建工具、get 调用本系统演示样例、get 调用其它系统演示样例

一.get 标签概述 通俗来讲,get 标签是Phpcms定义的能直接调用数据库里面内容的简单化.友好化代码,她可调用本系统和外部数据,仅仅有你对SQL有一定的了解,她就是你的绝世好剑!也就是适合熟悉SQL语句的人使用.有了她,我们打造个性化的站点,能很方便的调用出数据库里面指定的内容.通过条件限制,我们能够调用出不同条件下的不同数据. 二.get标签样式 {get dbsource=" " sql=" "} {/get} 三.get 标签语法 1.get标签属性值

JDBC连接MySQL数据库及演示样例

JDBC是Sun公司制定的一个能够用Java语言连接数据库的技术. 一.JDBC基础知识         JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,能够为多种关系数据库提供统一訪问,它由一组用Java语言编写的类和接口组成.JDBC为数据库开发者提供了一个标准的API,据此能够构建更高级的工具和接口,使数据库开发者能够用纯 Java API 编写数据库应用程序,而且可跨平台执行,而且不受数据库供应商的限制.

java设计模式演示样例

创建模式 1.工厂方法模式(Factory Method)  将程序中创建对象的操作,单独出来处理,创建一个产品的工厂接口,把实际的工作转移到详细的子类.大大提高了系统扩展的柔性,接口的抽象化处理给相互依赖的对象创建提供了最好的抽象模式. public class TestFactoryMethod { public static void main(String[] args) { AnimalFactory af=new DogFactory(); Animal1 a=af.getAnima