[英]C - Segmentation fault with struct
如果這是一個容易解決的問題,我真的很抱歉,但是我是一個初學者。 我有一項工作要向堆棧結構中編寫一些函數。 結構已給出。 我無法擺脫push()行“ s-> elements ...”中的細分錯誤,不知道經過數小時的谷歌搜索之后出了什么問題。
這里的代碼:
#define STACK_SIZE 5
#include <stdio.h>
#include <stdlib.h>
typedef struct stackADT {
int elements[STACK_SIZE];
int count;
} stack;
void initialize(stack *s)
{
stack *newStack;
newStack = malloc(sizeof(*newStack));
newStack->count = 0;
s = newStack;
}
int push(stack *s, int value)
{
if(s->count == 5) return -1;
else {
s->elements[s->count++] = value;
return s->elements[s->count-1];
}
}
int main()
{
stack* sA;
stack* sB;
initialize(sA);
initialize(sB);
printf("%d\n",push(sA,3));
return 0;
}
因為您要按值傳遞兩個指針(因此實際上是傳遞指針的副本),所以將初始化函數更改為int initilize(stack **s)
和s = newStack;
到*s = newStack;
然后像這樣initialize(&sA); initialize(&sB);
調用initialize initialize(&sA); initialize(&sB);
initialize(&sA); initialize(&sB);
除非您必須這樣做,否則您實際上不應該動態分配對象,而且您也不能free()
分配的內存,這是內存泄漏。
當您將指針傳遞給函數時,該函數會收到該指針的副本 。 除非您正在更改/創建指針的開始地址 ,否則通常這沒問題。
在您的情況下, sA
和sB
包含地址(當您傳遞它們進行initialize
時,它們是什么都沒有的指針)。 因此,您的initialize
函數必須使用指針的地址而不是指針本身 ,才能為指針分配一個地址,該地址將在main
可見。 例如:
void initialize(stack **s)
{
stack *newStack;
newStack = malloc(sizeof(*newStack));
newStack->count = 0;
*s = newStack;
}
...
initialize (&sA);
取消引用上面的雙指針**s
(例如*s = newStack;
),將newStack
的地址分配為指針s
的值。
我還建議在將newStack
的位置分配給*s
之前檢查分配是否成功:
void initialize(stack **s)
{
stack *newStack;
if (!(newStack = malloc(sizeof(*newStack)))) {
fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
exit (EXIT_FAILURE);
}
newStack->count = 0;
*s = newStack;
}
我認為您需要以下內容
#include <stdio.h>
#define STACK_SIZE 5
typedef struct stackADT
{
int elements[STACK_SIZE];
int count;
} stack;
void initialize( stack *s )
{
s->count = 0;
}
int push( stack *s, int value )
{
return s->count == STACK_SIZE ? -1 : ( s->elements[s->count++] = value );
}
int main(void)
{
stack sA;
stack sB;
initialize( &sA );
initialize( &sB );
printf( "%d\n", push( &sA, 3 ) );
return 0;
}
您收到分段錯誤,因為您試圖將push()
中的值分配給內存的未分配區域。 initialize()
可成功分配內存並使用count = 0
對其進行初始化,但是您對s = newStack
分配不起作用。 正如David和Alejandro指出的那樣,您正在傳遞“指針的副本”。 本質上,您傳遞的是未初始化的stack
變量的地址,但是您並未傳遞該函數用新地址更新該變量的方法。 您需要將指針傳遞給堆棧指針。 (也稱為第二級指針。)這意味着initialize()
將接收包含堆棧結構的內存地址的變量的內存地址。 這樣,該函數可以將二級指針的指針的指針分配給已分配堆棧的地址。
僅僅看一下代碼,可能會更容易理解:
#define STACK_SIZE 5
#include <stdio.h>
#include <stdlib.h>
typedef struct stackADT {
int elements[STACK_SIZE];
int count;
} stack;
void initialize(stack **s)
{
stack *newStack;
newStack = malloc(sizeof(*newStack));
if(NULL == newStack){
// Malloc could not allocate memory
// for newStack.
// Set s to NULL to indicate the error
s = NULL;
// Return prematurely
return;
} // else, malloc succeeded
newStack->count = 0;
// Assign the value of the malloced stack pointer to the pointee of stack **s
*s = newStack;
}
int push(stack *s, int value)
{
if( s->count == STACK_SIZE ){
// Stack has too many elements.
// Return with error value (-1)
return -1;
} else {
// Assign the new value to the current last index
s->elements[s->count] = value;
// Add count to indicate a new variable has been added
s->count++;
// Use the array to return the value just added
return s->elements[ (s->count - 1) ];
}
}
int main()
{
stack* sA;
stack* sB;
// Send the function a pointer to the stack pointer
initialize(&sA);
initialize(&sB);
if(sA == NULL){
puts("Could not allocate the memory for stack variable sA.\n");
return -1;
}
printf("%d\n", push(sA, 3) );
// Clean up the memory
free(sA);
free(sB);
return 0;
}
我還稍微修改了代碼以拆分push()
函數中的value
分配,並添加了malloc()
錯誤檢查。
注意 : 如果您喜歡它,我建議您使用Vlad的推功能。 它更短,更簡潔; 但是,它犧牲了可讀性。 由於您是初學者,所以我決定將其擴展可能更容易理解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.