c语言 段错误 指针,野指针引发的段错误(附解决方法)

写了一个静态栈的程序,但是在不同的调用中,出现的结果完全不一样。

编译器是,操作系统是Ubuntu9.04,CPU是AMD4400,但是装的是32位的操作系统。

$ gcc --version

gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3

Copyright (C) 2008 Free Software Foundation, Inc.

This is free software; see the source for copying conditions. There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

下面是静态栈的源程序:

/*file link_stack.h*/

#ifndef __LINK_STACK_H

#define __LINK_STACK_H

#define TRUE 1

#define FALSE 0

#define STACK_INIT_SIZE 50

#define STACK_INCREASE 10

typedef int type;

typedef struct node{

type* top;

type* base;

int size;

}stack;

stack* stack_init(stack* p);

int stack_is_exist(stack* p);

stack* stack_destroy(stack* p);

int stack_is_empty(stack* p);

int stack_length(stack* p);

int stack_get_top(stack* p);

stack* stack_push(stack* p, type data);

stack* stack_pop(stack* p, type *data);

int stack_print(stack* p);

#endif

/*file link_stack.c*/

/*这是一个静态链表栈*/

#include

#include

#include "link_stack.h"

/*由于top保存的是栈的最上面一个元素之上的指针,所以在压栈时top++,出栈时--top*/

stack* stack_init(stack* p){

p->base = (type *)malloc(STACK_INIT_SIZE * sizeof(type));

if (!p->base){

printf("malloc error./n");

exit(1);

}

p->top = p->base;

p->size = STACK_INIT_SIZE;

return p;

}

int stack_is_exist(stack* p){

if (p == NULL)

return FALSE;

else

return TRUE;

}

stack* stack_destroy(stack* p){

if (!stack_is_exist(p))

return FALSE;

free(p->base);

return NULL;

}

int stack_is_empty(stack* p){

if (!stack_is_exist(p))

return FALSE;

if(p->base == p->top)

return TRUE;

else

return FALSE;

}

int stack_length(stack* p){

if (!stack_is_exist(p))

return FALSE;

if (stack_is_empty(p)){

printf("stack is empty./n");

exit(1);

}

return p->top - p->base;

}

type stack_get_top(stack* p){

if (stack_is_empty(p)){

printf("stack is empty./n");

exit(1);

}

return *(p->top - 1);

}

stack* stack_push(stack* p, type data){

if (!stack_is_exist(p))

return FALSE;

if (p->top - p->base >= p->size){

p->base = (type*)realloc(p->base, (p->size + STACK_INCREASE) * sizeof(type));

if (!p->base){

printf("realloc error./n");

exit(1);

}

}

*((p->top)++) = data;

return p;

}

stack* stack_pop(stack* p, type *data){

if (!stack_is_exist(p))

return FALSE;

*data = *((--p->top));

return p;

}

int stack_print(stack* p){

int i;

printf("All data ");

for (i = 0; i < stack_length(p); i++)

printf("%3d ", *(p->base + i));

printf("/n");

return 0;

}

下面的源代码test.c用

$gcc link_stack.c test.c

编译正确,但是加上-O1 -O2或者-O3时就会出现运行时的段错误

/*file test.c*/

#include

#include

#include "link_stack.h"

/*gcc lnk_stack.c test.c*/

int main(int argc, char *argv[]){

stack* p;

int i;

type data;

p = stack_init(p);

for (i = 0; i < 6; i++){

p = stack_push(p, 3 * i);

}

stack_print(p);

p = stack_pop(p, &data);

printf("data %d/n", data);

stack_print(p);

data = stack_get_top(p);

printf("data %d/n", data);

return 0;

}

下面的源代码convert.c用

$gcc link_stack.c convert.c

编译时就会出现段错误,加上-O1 -O2或者-O3时也会出现运行时的段错误

/*file convert.c*/

#include

#include

#include "link_stack.h"

int main(int argc, char* argv[]){

stack* p;

type data, e;

int bit;

printf("Enter the data you wan to convert:");

scanf("%d", &data);

printf("Enter the bit:");

scanf("%d", &bit);

p = stack_init(p);

while(data){

p = stack_push(p, data % bit);

data /= bit;

}

while (!stack_is_empty(p)){

p = stack_pop(p, &e);

printf("%d", e);

}

stack_destroy(p);

printf("/nFinished/n");

return 0;

}

对于convert.c这个函数。

就算在main函数中初始化stack* p = NULL,然后调用stack_init(p),也会出段错误。

问题看来是stack_init函数不能正确执行,具体原因还弄不清楚。

对于段错误来说,通常 是由于读写了不访读写的内存地址。

实际上,在convert.c和test.c的main函数中,stack* p的写法有问题,因为这个指针属于野指针,没有一个内存区域。

应写成

stack m, *p;

p = &m;

这也是涉及的指针的所有程序书写时必须注意的一点,不能上来就直接定义一个指针,必须确保这个指针指向一个数据类型 。

一重指针

int a, *p;

p = &a;

两重指针

int a, *p, **q;

p = &a;

q = &p;

第二条语句*p =a 连接着q与a,如果去掉,中间就会断链,出现野指针。

后面的stack_init 的p->base才有一个空间供它存malloc的首地址,如果不声名stack m; p->base就不知道存什么位置,

最后理所当然的是段错误了。

后面补充一点,如果你在一个自定义函数里使用malloc,然后拿到main函数里去调用,不出错的方法有两种:

1. 入口参数用两重指针,指向你想保存内存起始地址的一个指针变量。

2. 把malloc的内存起始地址做为返回值。

这两种方法也是C语言的函数参数传递的两种方法。如果不用这两种中的一种,那么自定义函数调用结束之后,malloc的空

间会被收回。到最后会出现段错误。

0818b9ca8b590ca3270a3433284dd417.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值