[英]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.