[英]Segmentation fault in stack in push Function C language
当我启动程序时,我遇到了问题,它在功能Full并按下第70和78行(Linux)时崩溃了。 我尝试修复它,但是我总是在同一个地方崩溃。
#include <stdio.h>
#define SIZE 64
struct stack{
int TowerTop;
int Elem[SIZE];
};
/* Forward Declarations */
void push(int Elem, struct stack *x);
int create (struct stack *x);
int full(const struct stack *x);
void pop(struct stack *x);
int lolol(struct stack *x,struct stack *x2,struct stack *x3,int a);
void main() {
int j;
int a = 5;
//scanf("%d",&a);
struct stack Tower1;
struct stack Tower2;
struct stack Tower3;
create(&Tower1);
create(&Tower2);
create(&Tower3);
for(int i=0; i<=SIZE-1; i++) {
Tower1.Elem[i]=0;
Tower2.Elem[i]=0;
Tower3.Elem[i]=0;
}
for(int i=0; i<=a; i++){
Tower1.Elem[i]=i+1;
}
// Display initial tower setup
for(int i=0; i<a; i++){
printf("%d %7d %7d\n",Tower1.Elem[i],Tower2.Elem[i],Tower3.Elem[i]);
}
lolol(&Tower1,&Tower2,&Tower3,a);
// Display Tower after move made by lolol
printf("%d\n", j);
for(int i=0; i<a; i++) {
printf("%d %7d %7d\n",Tower1.Elem[i],Tower2.Elem[i],Tower3.Elem[i]);
}
}
int lolol(struct stack *x,struct stack *x2,struct stack *x3,int a) {
if(a == 1) {
printf("\n Disk 1 move to");
push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]); j++;
pop(x->Elem[x->TowerTop]);
return 0;
}
lolol(x, x3, x2, a-1);
push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]); j++;
pop(x->Elem[x->TowerTop]);
lolol(x3, x2, x, a-1);
}
int create(struct stack *x) {
x->TowerTop = -1;
}
int full(const struct stack *x) {
if (x->TowerTop == SIZE-1) {
return 1;
} else {
return 0;
}
}
void push(int Elem, struct stack *x){
if(full(x)) {
printf("Stack is full");
} else {
x->TowerTop++;
x->Elem[x->TowerTop]=Elem;
}
}
void pop( struct stack *x) {
if(x->TowerTop== -1) {
printf("Empty");
} else {
x->TowerTop--;
}
}
我们将一起调试您的代码。 但是首先,我将向您详细介绍如何在论坛上提问(因此请在StackOverflow上)。
首先,因为我们都在这里为您提供帮助,所以没有“尽快”的方法。 我们会尽力而为,可能会或可能不会准时。 然后,请使用您的代码再次阅读您的消息并问自己,这可读吗? 我确实希望您的代码在文件中看起来不一样,并且您以某种方式使复制/粘贴失败,因为该代码非常不可读。
我将跳过此步骤的详细信息,但基本上是缩进,在需要时添加空格等。
#include <stdio.h>
#define SIZE 64
struct stack
{
int TowerTop;
int Elem[SIZE];
};
void push(int Elem, struct stack *x);
void pop(struct stack *x);
int create (struct stack *x);
int full(const struct stack *x);
int lolol(struct stack *x, struct stack *x2, struct stack *x3, int a);
int a;
int j;
void main()
{
//scanf("%d", &a);
a = 5;
struct stack Tower1;
struct stack Tower2;
struct stack Tower3;
create(&Tower1);
create(&Tower2);
create(&Tower3);
for (int i = 0; i <= SIZE - 1; i++)
{
Tower1.Elem[i] = 0;
Tower2.Elem[i] = 0;
Tower3.Elem[i] = 0;
}
for (int i = 0; i <= a; i++)
{
Tower1.Elem[i] = i + 1;
}
for (int i = 0; i < a; i++)
{
printf("%d %7d %7d\n", Tower1.Elem[i], Tower2.Elem[i], Tower3.Elem[i]);
}
lolol(&Tower1, &Tower2, &Tower3, a);
printf("%d\n", j);
for (int i = 0; i < a; i++)
{
printf("%d %7d %7d\n", Tower1.Elem[i], Tower2.Elem[i], Tower3.Elem[i]);
}
}
int lolol(struct stack *x, struct stack *x2, struct stack *x3, int a)
{
if (a == 1)
{
printf("\n Disk 1 move to");
push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]);
j++;
pop(x->Elem[x->TowerTop]);
return 0;
}
lolol(x, x3, x2, a - 1);
push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]);
j++;
pop(x->Elem[x->TowerTop]);
lolol(x3, x2, x, a - 1);
}
int create(struct stack *x)
{
x->TowerTop = -1;
}
int full(const struct stack *x)
{
if (x->TowerTop == SIZE-1)
{
return 1;
}
else
{
return 0;
}
}
void push(int Elem, struct stack *x)
{
if (full(x))
{
printf("Stack is full");
}
else
{
x->TowerTop++;
x->Elem[x->TowerTop] = Elem;
}
}
void pop(struct stack *x)
{
if (x->TowerTop == -1)
{
printf("Empty");
}
else
{
x->TowerTop--;
}
}
请不要说我没有更改任何逻辑或类型或任何其他内容。
实际上,我稍后可能会再讲到这一点,但是我快速阅读了一些基本的知识。 main
函数应始终返回一个int
。 根据C标准,只能使用两种方式声明main
函数: int main(void)
(不带参数)或int main(int argc, char *argv[]);
(采用命令行参数)。
然后,您必须知道两个变量a
和j
是文件的全局变量。 这意味着您可以在同一源文件中的任何位置访问它们。 听起来不错,不起作用。 除非没有其他选择(例如,使用sigaction
),否则永远不要执行全局变量。 在您的情况下,确实不需要它们。
最后,评论。 请赞扬您的代码。 虽然在这里可以轻松理解大多数内容,但是快速浏览一下代码时,函数lolol
(该名称根本没有意义)正在执行我不理解的操作。
gcc file.c
=> 4条警告。 除非您知道自己在做什么,并且是一位经验丰富的C程序员-否则(尚未!),您在编译时不应有任何警告。 此外,您应该使用-Wall -Wextra
开关进行编译。 这将引发更多警告,但允许您在错误甚至还没有存在之前就对其进行捕捉。
因此,我们将修复警告:
warning: return type of 'main' is not 'int' [-Wmain]
。 好吧,让我们切换一下。 正如我之前所说, void main()
变为int main(void)
。 file.c:64:34: warning: passing argument 2 of 'push' makes pointer from integer without a cast [-Wint-conversion]
=>好吧,这里您使用的是我假设您编写的push
函数。 但是,此函数在将int
传递给它时,将int
作为第一个参数,将struct stack *
作为第二个参数。 让我们修复一下: push(x->Elem[x->TowerTop], x2->Elem[x2->TowerTop]);
成为push(x->Elem[x->TowerTop], x2);
,因为您要将x->Elem[x->TowerTop]
推入x2
堆栈的顶部。 pop
线66, push
线70和pop
线72。 file.c:74:1: warning: control reaches end of non-void function [-Wreturn-type]
=>我仍然不确定lolol
应该做什么,所以我将只需在其末尾添加return 0
,然后将create
函数切换为void
类型。 这是更正的代码:
#include <stdio.h>
#define SIZE 64
struct stack
{
int TowerTop;
int Elem[SIZE];
};
void push(int Elem, struct stack *x);
void pop(struct stack *x);
void create (struct stack *x);
int full(const struct stack *x);
int lolol(struct stack *x, struct stack *x2, struct stack *x3, int a);
int a;
int j;
int main(void)
{
//scanf("%d", &a);
a = 5;
struct stack Tower1;
struct stack Tower2;
struct stack Tower3;
create(&Tower1);
create(&Tower2);
create(&Tower3);
for (int i = 0; i <= SIZE - 1; i++)
{
Tower1.Elem[i] = 0;
Tower2.Elem[i] = 0;
Tower3.Elem[i] = 0;
}
for (int i = 0; i <= a; i++)
{
Tower1.Elem[i] = i + 1;
}
for (int i = 0; i < a; i++)
{
printf("%d %7d %7d\n", Tower1.Elem[i], Tower2.Elem[i], Tower3.Elem[i]);
}
lolol(&Tower1, &Tower2, &Tower3, a);
printf("%d\n", j);
for (int i = 0; i < a; i++)
{
printf("%d %7d %7d\n", Tower1.Elem[i], Tower2.Elem[i], Tower3.Elem[i]);
}
}
int lolol(struct stack *x, struct stack *x2, struct stack *x3, int a)
{
if (a == 1)
{
printf("\n Disk 1 move to");
push(x->Elem[x->TowerTop], x2);
j++;
pop(x);
return 0;
}
lolol(x, x3, x2, a - 1);
push(x->Elem[x->TowerTop], x2);
j++;
pop(x);
lolol(x3, x2, x, a - 1);
return 0;
}
void create(struct stack *x)
{
x->TowerTop = -1;
}
int full(const struct stack *x)
{
if (x->TowerTop == SIZE-1)
{
return 1;
}
else
{
return 0;
}
}
void push(int Elem, struct stack *x)
{
if (full(x))
{
printf("Stack is full");
}
else
{
x->TowerTop++;
x->Elem[x->TowerTop] = Elem;
}
}
void pop(struct stack *x)
{
if (x->TowerTop == -1)
{
printf("Empty");
}
else
{
x->TowerTop--;
}
}
无需SIGSEGV即可编译和运行。
我将讨论更高级的主题,但这可能对您有用。 首先,获得有关堆栈及其工作方式的更多信息,因为我不确定您是否已完全理解它。
另外,要调试程序,您可以使用valgrind
,它是一个内存检查器工具,它非常有用,并且总是派上用场。 要使用它,请在编译时添加标志-g
。
我建议也研究GNU Linux调试器gdb
。 很强大。
可以将full
函数更改为简单的return x->TowerTop == SIZE - 1
。 它避免了分支,因此将运行得更快。
那就是所有人。 仍然不确定您的代码应该做什么,但您只询问如何修复段错误。 现在,请记住。 编译时不要发出任何警告。
谢谢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.