LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1392|回复: 10

一个简单的c程序 麻烦大家帮看一下

[复制链接]
发表于 2010-5-5 22:43:34 | 显示全部楼层 |阅读模式
#include<stdio.h>
#include<stdlib.h>
typedef struct{
        int *base;
        int *top;
}SqStack;
Push(SqStack *s,int x){
        *(s->top)=x;
        s->top++;
}
int Pop(SqStack *s){
        s->top--;
        return *s->top;
}
int main(){
        int n,m;
        SqStack *Stack;
        Stack->base=(int*)malloc(30*sizeof(int));
        Stack->top=Stack->base;

        printf("please input a number:\n");
        scanf("%d",&n);
        while(n){
        Push(Stack,n%2);
        n=n/2;}
        while(Stack->top!=Stack->base){
                m=Pop(Stack);
                printf("%d",m);
        }
        printf("\n the end \n");
}
编译能够通过,但是运行的时候提示段错误,用gdb跟踪发现到Stack->base=(int*)malloc(30*sizeof(int));的时候出现了错误,malloc和结构体指针这样使用应该是没有问题的啊,但是为什么会出现段错误呢?
发表于 2010-5-6 09:04:28 | 显示全部楼层
bug....
回复 支持 反对

使用道具 举报

发表于 2010-5-6 09:06:29 | 显示全部楼层
使用了虚拟的指针,相当于使用了虚拟经济。
回复 支持 反对

使用道具 举报

发表于 2010-5-6 09:13:59 | 显示全部楼层
楼主这是做一个十进制到二进制转换的程序吧?
你只声明了Stack指针,并没有让它指向一块有意义的内存空间,就给它赋值了(Stack->base=(int*)malloc(30*sizeof(int));),因为未初始化的局部非静态变量的初值是不定的,Stack此时不知指向内存的什么位置,然后楼主就给它指指向的位置写数据,当然会引起段错误
解决办法就是加一个"Stack = (SqStack*)malloc(sizeof(SqStack));",就可以了

其实这个编译的时候如果加上“-Wall”参数是有(warning: ‘Stack’ is used uninitialized in this function)这样的警告的,告诉你Stack没有初始化。
回复 支持 反对

使用道具 举报

发表于 2010-5-6 22:10:52 | 显示全部楼层
楼上正解,必须对stack初始化
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-5-7 10:39:47 | 显示全部楼层
Post by liwangli;2088150
楼主这是做一个十进制到二进制转换的程序吧?
你只声明了Stack指针,并没有让它指向一块有意义的内存空间,就给它赋值了(Stack->base=(int*)malloc(30*sizeof(int));),因为未初始化的局部非静态变量的初值是不定的,Stack此时不知指向内存的什么位置,然后楼主就给它指指向的位置写数据,当然会引起段错误
解决办法就是加一个"Stack = (SqStack*)malloc(sizeof(SqStack));",就可以了

其实这个编译的时候如果加上“-Wall”参数是有(warning: ‘Stack’ is used uninitialized in this function)这样的警告的,告诉你Stack没有初始化。
就是你说的这样,但是如果我这样声明指针static SqStack *Stack,为什么也有问题呢,static不是默认初始化吗?
回复 支持 反对

使用道具 举报

发表于 2010-5-7 12:34:31 | 显示全部楼层
Post by ncutwy;2088388
就是你说的这样,但是如果我这样声明指针static SqStack *Stack,为什么也有问题呢,static不是默认初始化吗?


默认初始化到NULL的啊, 还是不能往里写, 得分配空间

PS: static 主要是声明静态量和private的意思, 不要只为初始化为NULL来用
回复 支持 反对

使用道具 举报

发表于 2010-5-7 13:04:27 | 显示全部楼层
Post by ncutwy;2088388
就是你说的这样,但是如果我这样声明指针static SqStack *Stack,为什么也有问题呢,static不是默认初始化吗?


就像楼上说的那样,全局变量和静态局部变量会被初始化为0,对于指针来说,就是初始化为NULL,当然还是不对。

指针变量存的仅仅是地址,如果存的地址不是有意义的,利用指针对这段内存进行访问当然是错误的。

楼主要么先定义一个SqStack型变量,再定义一个此类型的指针,再让指针指向这个变量(SqStack i; SqStack *Stack = &i;),这样指针Stack指向的是在程序在栈中分配的有意义的内存空间;

要么用malloc在堆中分配一段有意义的空间,并让指针指向它(SqStack *Stack = (SqStack*)malloc(sizeof(SqStack));)。

虽然操作系统为每个进程分配了4GB的虚拟地址空间,但并不意味着可以随便使用。分页管理的虚拟地址空间,有些地方是不可写的(比如代码段或地址为0)以及没有分配给进程用的地址,如果想写入这些地方,就会引起段错误。

即使指针中随机地址正好落在栈,堆和数据段这些可写的地方,固然不会引起段错误,但也意味着原本在这些地方存的有意义的数据被破坏了,也有很大的可能让程序出错。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-5-7 22:24:06 | 显示全部楼层
十分感谢,呵呵
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-5-7 22:26:50 | 显示全部楼层
楼主说的这么详细,这些内容我都知道,书上看的,但是就是不会自己拿来分析问题,十分感谢。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表