C - 结构分段错误
C - Segmentation fault with struct
如果这是一个简单的问题,我真的很抱歉,但我是初学者。
我有一项任务是将一些函数写入堆栈结构。给出了结构。我无法摆脱 push() 行中的分段错误 "s->elements..."
经过几个小时的谷歌搜索和搜索后,我不知道出了什么问题。
代码如下:
#define STACK_SIZE 5</p>
#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);
你真的不应该动态分配对象,除非你必须这样做,而且你没有free()
分配你分配的内存,那是内存泄漏。
当您将指针传递给函数时,函数会接收到指针的副本。这通常没问题,除非你是 changing/creating 指针的起始地址。
在您的例子中,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 指出的那样,你传递的是 "a copy of the pointer." 本质上,你传递的是未初始化的 stack
变量的地址,但你没有传递给函数一种用新地址更新该变量的方法.您需要向它传递一个指向堆栈指针的指针。 (也称为二级指针。)这意味着 initialize()
将接收保存堆栈结构内存地址的变量的内存地址。因此,该函数然后可以将二级指针的指向对象分配给 malloced 堆栈的地址。
也许看代码会更容易理解:
#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的推送功能。它更短更简洁;但是,它牺牲了可读性。由于您是初学者,我决定将其展开可能更容易理解。
如果这是一个简单的问题,我真的很抱歉,但我是初学者。 我有一项任务是将一些函数写入堆栈结构。给出了结构。我无法摆脱 push() 行中的分段错误 "s->elements..." 经过几个小时的谷歌搜索和搜索后,我不知道出了什么问题。
代码如下:
#define STACK_SIZE 5</p>
#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);
你真的不应该动态分配对象,除非你必须这样做,而且你没有free()
分配你分配的内存,那是内存泄漏。
当您将指针传递给函数时,函数会接收到指针的副本。这通常没问题,除非你是 changing/creating 指针的起始地址。
在您的例子中,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 指出的那样,你传递的是 "a copy of the pointer." 本质上,你传递的是未初始化的 stack
变量的地址,但你没有传递给函数一种用新地址更新该变量的方法.您需要向它传递一个指向堆栈指针的指针。 (也称为二级指针。)这意味着 initialize()
将接收保存堆栈结构内存地址的变量的内存地址。因此,该函数然后可以将二级指针的指向对象分配给 malloced 堆栈的地址。
也许看代码会更容易理解:
#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的推送功能。它更短更简洁;但是,它牺牲了可读性。由于您是初学者,我决定将其展开可能更容易理解。