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