c语言程序中,SIGSEGV越界访问内存访问越界的错误

故意对malloc分配的内存进行越界访问竟然没报错(c语言)_百度知道
故意对malloc分配的内存进行越界访问竟然没报错(c语言)
代码的大致内容:
int *p1 = (int *)malloc(4);
bzero(p1,MALLOC_SIZE);
*(p1+1) = 1;
*(p1+2) = 1;
*(p1+3) = 1;
*(p1+4) = 1;
*(p1+5) = 1;
最后分别在两台上运行它,
有一台报 SIGABRT 错误(怎样才能用 mal...
我有更好的答案
c/c++语言的危险就在这。你只要不去动操作系统保留的内存,程序就不会死。有些时候内存越界还会影响程序流程,比如for循环控制变量为i,在for循环内部进行内存申请,如果控制不好就有可能无意的修改i的值,导致循环次数有错,甚至导致这个for循环死成循环。
这是你自己回答的还是系统推荐的回答,怎么感觉回答的不是我问的问题
不是系统推荐的。我在解答你的问题啊!malloc确实是分配了4字节,但仅仅是给了程序4个字节的合法使用空间,非法使用是控制不了的。而且两台机器的环境不一样,同样是int *p1 = (int *)malloc(4);但是p1的地址不同,导致可能p1+4后面被系统保留,或者p1+4后面没有被系统保留,所以造成了程序在两台机器上表现不同。
采纳率:54%
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。关于C语言越界访问内存的问题
申明:本文系原创,转载时请注明出处,本人保留追究责任的权利。
原文地址:http://hi.baidu.com/surfmygod/blog/item/1b427f16caaf53d0.html
今天看到这样一个例子:
int *p = (int *)0012FF7C;
*p = 0x100;
使用VC6.0编译运行一下,正常,不报错。如果你debug一下,会发现第三行变量定义同时赋初值结果正确,p指针的值确实是0012FF7C,接着运行到第四行,这里问题来了,你会发现p指针的值变成0x100而*p产生错误。大家想了,按理说将*p赋值0x100应该是p所指向的内存值改变为0x100,而p指针的值不变。这里为什么却把指针的值变了呢?《C语言深度解剖》一书认为VC6.0错了,这是一个bug。我说,我们都被VC忽悠了。为什么这么说?请参看清华大学出版社谭浩强版的《C语言程序设计》一书,C语言规定不能将一个整数直接赋值给指针变量。VC6.0编译上面的程序不会出错,并不代表你能执行得到正确的结果。这一块VC编译时对语法的检查比较宽松,允许你直接使用整型赋值给指针,从而造成了上述现象。
下面继续看如下一个例子:
int i = 0;
int *p = (int *)0012FF7C;
*p = 0x100;
printf("%p,%p,%x,%x",&i,p,*p,i);
输出结果会是什么?在VC中运行一下吧,你会得到:12FF7C,100,100
别惊讶,确实是这个结果。下面我们来分析一下为什么会产生这个结果。
p和&i恰巧相同?不是的,我们给的p在VC中每次定义第一个变量都不变,所以故意将p和&i弄成了一样的。好了,现在定义的i变量被系统分配在了以0012FF7C地址开始的一段内存单元,而p又被我们定义指向了0012FF7C内存单元,此时修改*p就等于修改i,于是得到上述值。等等等等,刚上面不是说给*p赋值使得p变成0x100了么?这里怎么不变了?你可以试着删除第三行i的定义,再运行你会发现系统会报错。为什么会这样?因为你使用了0012FF7C内存单元的值。有没有i的定义差别在于:定义了i以后系统将0012FF7C起始的一段内存使用权交给我们的程序,此时0012FF7C不再是未知的存储区域,我们的程序有权限使用他,而去掉定义以后,我们的程序对这块内存没有了支配权,从而报错。这样就比较好理解了。在VC中虽然可以用整型数直接给指针赋值,但是能不这样用就不这样用,这可能带来意想不到的错误或风险。老老实实使用取地址运算符&或者间接访问运算符*来操作吧。
还有一个内存越界访问的问题。在C中你定义一个数组a[10],你可以打印a[-1]或是a[10]么?在VC中试一下你会发现,这样是可以的。不光a[-1]和a[10],a[-100]、a[1000]同样也可以。其实C语言里对于数组的约束是很宽泛的,数组下标越界并不会报错,同样可以使用。但是别试图写数组下标越界的内存,那会给你意想不到的“惊喜”。道理和上面的例子是一样的,特殊情况需要访问的时候可以越界读取内存的值,但是你要知道你自己读取的是什么,是不是你的程序可控的内存范围,如果不是,还是打消这个念头吧。
记住一句话:容忍不代表你可以为所欲为。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。17:41 提问
程序运行跳出来这个
什么问题??
it stopped with signal SIGSEGV,Segmentation fault
-----------------------------------------------------以下正文
int a[100][100];
#define X0 100
#define Y0 100
#define WIDTH 20
typedef struct
typedef struct
//-------------------------------顺序栈
class Stack
Stack(int n=0);
bool isEmpty();
bool isFull();
bool push(const NODE k);
bool pop();
Stack::Stack(int n)
p=new NODE[n];
Stack::~Stack(){
delete []p;
bool Stack::isEmpty(){
return(top==-1);
bool Stack::isFull(){
return(top&=size-1);
bool Stack::push(const NODE k){
if(!isFull()){
bool Stack::pop(){
if(!isEmpty()){
NODE k=p[top];
//。-----------------------------画框
void Init()
fp=fopen("mice.txt","r");
fscanf(fp,"%d%d%d%d%d%d",&xnum,&ynum,&start.x,&start.y,&end.y,&end.x);//24 24 1 1 24 1
for(j=0;j&=ynum+1;j++)
for(i=0;i&=xnum+1;i++)
a[j][i]=1;
for(j=1;j&=j++)
for(i=1;i&=i++)
fscanf(fp,"%d",&a[j][i]);
fclose(fp);
grid.nownode =//--------------初始位置 (1,1)
void reaction(Stack path,int x,int y){
grid.nownode.x=x;
grid.nownode.y=y;
path.push(grid.nownode);
//PrintNum(120,50,grid.nownode.x);
//PrintNum(140,50,grid.nownode.y);
//DrawRectangle(X0+grid.nownode.y*WIDTH,Y0+grid.nownode.x*WIDTH,X0+(grid.nownode.y+1)*WIDTH,Y0+(grid.nownode.x+1)*WIDTH,MOUSECOLOR);
int MouseMove(Stack path)
x=grid.nownode.x;
y=grid.nownode.y;//--------------现在位置
if (end.x==x && end.y==y){
grid.nownode.x=x;
grid.nownode.y=y;
path.push(grid.nownode);
a[x][y]=1;//------------------------------------------------似乎指出的是这里
if(a[x][y+1]==0)
reaction(path,x,y+1);
else if(a[x+1][y]==0)
reaction(path,x+1,y);
else if(a[x][y-1]==0)
reaction(path,x,y-1);
else if(a[x-1][y]==0)
reaction(path,x-1,y);
path.pop();
grid.nownode.x=path.p[path.top].x;
//上一个值作现在位置
grid.nownode.y=path.p[path.top].y;
int main(){
Stack path(2000);
//---------------------//创建顺序表
path.push(start);
x=grid.nownode.x;
y=grid.nownode.y;//--------------现在位置
while(end.x!=x || end.y!=y)
MouseMove(path);
for(int i=0; i&=path.i++)
a[path.p[path.top].x][path.p[path.top].y]=2;
for(int i=0;i&=xnum+1;i++)
for(int j=0;j&=ynum+1;j++)
printf("%d",a[i][j]);
printf("\n");
scanf("%d",&x);
---------------------------------------------------mice.txt文件 (迷宫问题 C-FREE下)
24 24 1 1 24 1
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
按赞数排序
Linux系统的吧,可能是内存越界导致的。
用gdb单步跟踪一下吧,不然根本不知道蹦在哪里了。
也可以设置一下,崩溃会产生coredump文件,然后用gdb跟踪,应该很容易就找出问题了。
希望能够帮到你。
段错误应该就是访问了不该访问的地址吧,在main函数开始设个断点,一步一步往下走,看看问题出在哪个函数里边,
如果进入循环里边,可以输出一下循环的控制变量之类的,看看是在哪一步出错,比如i==n的时候出的错,就可以加一句if (i==n)cout&&"a"&&
之类的代码然后设断点到这里看看具体运行情况怎么回事。也可以直接在for循环语句这里设置断点情况。
这也太长了,内存给小了吧?
VS里Debug下打开call stack看看,能否先找到出错的函数调用。
这个是段错误,一般是指针指向了不该指向的地方
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐每天积累一点点
C语言系统内存被踩情况总结
C语言由于可以直接操作内存,给我们的编程带来了便利,同时也带来了内存写越界之类的问题,常常造成我们的系统crash。下面总结了我在工作中碰到的导致内存越界的各种场景,以供分析此类问题时作个参考。
1、直接写越界,包括1)栈空间变量写越界覆盖掉函数返回地址,导致函数返回时crash。2)全局变量写越界,导致覆盖掉符号表中排在这个全局变量后面的全局变量的值。
2、未初始化指针变量的值写操作。
3、指针释放了未置空,后续又被视为仍有效而进行写操作。
4、局部变量在生存期外被写,如1)一个线程写了另一个线程的局部变量。2)函数返回的局部变量被写。
5、数组没有初始化,接着调用strncpy只拷贝了覆盖掉部分空间,剩余空间可能是一个随机值,之后继续拿来使用。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!段错误(Segment Fault!)莫名的问题|程序编程
段错误或段违规(segmentation violation)应该已经很清楚,之前有过一篇文章介绍过"段模型"。
  在一般硬件中,段错误是由于"内存管理单元"(负责支持虚拟内存的硬件)的异常所致,而该异常则通常是由于解除引用一个未初始化或非法值的指针引起的。如果指针引用一个并不位于你的地址空间中的地址,操作系统便会对此进行干涉。一个小型的会引起段错误的程序如下:
  int *p = 0;
  *p = 17; //引起一个段错误
  一个微妙之处是,导致指针具有非法的值通常是由于不同的编程错误所引起的。和总线错误不同,段错误更像是一个间接的症状而不是引起错误的原因。
  一个更糟糕的微妙之处是,如果未初始化的指针恰好具有未对齐的值(对于指针所要访问的数据而言),它将会产生总线错误,而不是段错误。对于绝大多数架构的计算机而言确实如此,因为CPU先看到地址,然后再把它发送给MMU(内存管理单元)。
  通常导致段错误的几个直接原因:
  (1) 解除引用一个包含非法值的指针;
  (2) 解除引用一个空指针(常常由于从系统程序中返回空指针,并未经检查就使用)。
  (3) 在未得到正确的权限时进行访问。例如,试图往一个只写的文本段存储值就会引起段错误。
  (4) 用完了堆栈或堆空间(虚拟内存虽然巨大但绝非无限)。
  下面这个说法可能过于简单,但在绝大多数架构的绝大多数情况下,总线错误意味着CPU对进程引用内存的一些做法不满,而段错误则是MMU对进程引用内存的一些情况发生抱怨。
  以发生频率为序,最终可能导致段错误的常见编程错误是:
  1. 坏指针值错误:在指针赋值之前就用它来引用内存,或者向库函数传送一个坏指针(不要上当!如果编译器显示系统程序中出现了段错误,并不是因为系统程序引起了段错误,问题很可能还在存在于自己的代码中)。第三种可能导致坏指针的原因是对指针进行释放之后再访问它的内容。可以修改free语句,在指针释放之后再将它置为空值。
  free(p); p = NULL;
  这样,如果在指针释放之后继续使用该指针,至少程序能在终止之前进行信息转储。
  2. 改写(overwrite)错误:越过数组边界写入数据,在动态分配的内存两端之外写入数据,或改写一些堆管理数据结构(在动态分配的内存之前的区域写入数据就很容易发生这种情况)。
  p = malloc(256); p[-1] = 0; p[256] = 0;
  3. 指针释放引起的错误:释放同一个内存块两次,或释放一块未曾使用malloc分配的内存,或释放仍在使用中的内存,或释放一个无效的指针。一个极为常见的与释放内存有关的错误就是在 for(p= p=p-&next)这样的循环中迭代一个链表,并在循环体内使用 free(p) 语句。这样,在下一次循环迭代时,程序就会对已经释放的指针进行解除引用操作,从而导致不可预料的结果。
  详细出处参考:http://www.itqun.net/content-detail/238672.html
05/19 10:01
第一时间捕获段错误(segment fault)的详细信息
10:18 4798人阅读 评论(3) 收藏 举报 bufferstructlinuxnull测试gcc 目录(?)[+] 理解自报死因这个机制的前提 测试的例子 不使用gdb也能捕获段错误的详细信息,事实上,使用gdb是一件很麻烦的事情!第一,gdb功能太过强大,诊断个段错误真是大材小用,如果不会用还要学...其次,很多系统并没有安装这个工具.因此最好的办法就是&自报死因&.在Linux中,这是很容易做
12/02 15:13
捕获Linux段错误(Segment fault)并且打印错误堆栈 Linux上跑服务器如果遇到程序崩溃是一件很苦恼的事情, 再碰到重现很难的BUG, 估计只能通过传统的排查方法进行. 在编写本文前, 笔者使用过诸如libunwind等库进行错误时堆栈打印, 但是其本身由于需要引用第三方库, 使用还是稍微麻烦. 经过Google后, 居然找到一篇好文, 其通过捕获SIGSEGV信号, 并迫使程序进入gdb调试阶段, 利用gdb强大的调试功能可以进行各种错误跟踪, 此法已与Windows下程序崩溃
08/05 16:05
1.背景介绍 2.程序中常见的bug分类 3.程序调试器(如gdb)有什么用 4.段错误(Segmental fault)介绍 5.gdb调试入门
一.背景介绍 这个笔记主要介绍开源的程序调试器(gdb)的入门知识,目的是使unix/linux环境的编程新手能够快速学会使用gdb调试程序的方法,同时也是对我使用gdb的一个经验总结. 本文假设你能使用简单的unix/linux命令并能用gcc(GNU C Compiler, GNU C 语言编译器)编译程序,当然有编程经验更好.:) 为帮助你理
06/27 04:57
最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的&段错误&(Segmentation Fault).借此机会系统学习了一下,这里对Linux环境下的段错误做个小结,方便以后同类问题的排查与解决. 1. 段错误是什么 一句话来说,段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址.访问了系统保护的内存地址.访问了只读的内存地址等等情况.这里贴一个
02/20 19:07
1.段错误的定义 段错误:访问的内存超出了系统给这个程序的内存空间,通常这个值是由gdtr来保存的,gdtr是一个48位的寄存 器,其中的32位是保存由它指向的 gdt表,中间13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的 表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息.一旦一个程序发生了 越界访问,cpu就会产生相应的异常保护,于是se
05/06 05:51
Linux下c/c++开发之程序崩溃(Segment fault)时内核转储文件(core dump)生成设置方法 Linux下c/c++开发程序崩溃(Segment fault)通常都是指针错误引起的.以下是我们详细的对Linux core dump的调试技术进行的介绍: Linux core dump简介 有的程序可以通过编译, 但在运行时会出现Segment fault(段错误). 这通常都是指针错误引起的.但这不像编译错误一样会提示到文件-&行, 而是没有任?信息, 使得我们的调试变得困
11/24 00:11
linux 下c 程序 段错误 分析 ( 16:50:57) 转载 标签: it 分类: C/C++ fopen(&/var/spool/cron/tmp&,&w+&);/////////////////////////////////////////#include &sys/types.h&#include &sys/stat.h&#include &fcntl.h&#include &unistd.
11/13 06:18
core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump. (linux中如果内存越界会收到SIGSEGV信号,然后就会core dump) 在程序运行的过程中,有的时候我们会遇到Segment fault(段错误)这样的错误.这种看起来比较困难,因为没有任何的栈.trace信息输出.该种类型的错误往往与指针操作相关.往往可以通过这样的方式进行定位. 一 造成segment fault,产生co
04/21 02:48
Linux下发生段错误时如何产生core文件 Linux下的C程序常常会因为 内存访问错误等原因造成segment fault(段错误),此时如果系统core dump功能是打开的,那么将会有内存映像转储到硬盘上来,之后可以用gdb对core文件进行分析,还原系统发生段错误时刻的堆栈情况.这对于我们发现 程序bug很有帮助. 使用ulimit -a可以查看系统core文件的大小限制;使用ulimit -c [kbytes]可以设置系统允许生成的core文件大小,例如 ulimit -c 0 不产

我要回帖

更多关于 c语言内存错误 的文章

 

随机推荐