在 C 中自己的堆栈实现中的分段 11
Segmentation 11 in own stack implementation in C
我试图实现我自己的堆栈程序,但是当我初始化堆栈时,我得到了分段错误!
extern int stackInit(intstack_t* self){
self = malloc(sizeof(intstack_t));
if(self == NULL){
fprintf(stderr,"Out of memory.");
free(self);
exit(-1);
}
self->bottom = malloc(MINIMUM_SIZE * sizeof(int));
if(self->bottom == NULL){
fprintf(stderr,"Out of memory.");
free(self->bottom);
exit(-1);
}
self->top = self->bottom - 1;
self->allocated_top = self->bottom + MINIMUM_SIZE -1;
return 0;
}
int main()
{
intstack_t stack;
stackInit(&stack);
stackPush(&stack, 1);
stackPush(&stack, 2);
stackPush(&stack, 3);
}
extern void stackPush(intstack_t* self, int i){
//check if the stack is full and double its size if so.
if(self->top == self->allocated_top){
ptrdiff_t total = self->top - self->bottom +1;
ptrdiff_t new_total = GROWTH_FACTOR + total;
self->bottom = realloc(self->bottom, new_total * sizeof(int));
if(self->bottom == NULL){
fprintf(stderr,"Out of memory.");
free(self->bottom);
exit(-1);
}
self->top = self->bottom + total - 1;
self->allocated_top = self->bottom + new_total - 1;
}
*(++self->top) = i;
}
这是结构:
typedef struct
{
int* bottom;
int* top;
int* allocated_top;
} intstack_t;
当我用 valgrind 编译它时,我得到了这个:
使用大小为 8 的未初始化值
==2744731== 在 0x4008B2:stackPush(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中)
==2744731== by 0x4009AB: main (in /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack)
==2744731== 未初始化的值是由堆栈分配创建的
==2744731== 位于 0x400987:main(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中)
==2744731== 条件跳转或移动取决于未初始化的值
==2744731== 在 0x4007C5:stackPush(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中)
==2744731== by 0x4009AB: main (in /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack)
==2744731== 未初始化的值是由堆栈分配创建的
==2744731== 位于 0x400987:main(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中)
==2744731== 进程以信号 11 (SIGSEGV) 的默认操作终止:转储核心
==2744731== 地址 0x4005F4 映射区域的错误权限
==2744731== 在 0x4008B2:stackPush(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中)
==2744731== by 0x4009AB: main (in /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack)
问题源于您声明 init 函数采用 intstack_t *
但该指针已被复制。所以基本上是将局部变量栈的地址复制到一个局部变量中,然后通过malloc
返回地址的赋值在本地覆盖,所以stack
变量保持不变(未初始化)[=16] =]
一个解决方案是修改函数以使用双指针:
extern int stackInit(intstack_t **self) {
// instead of self you write (*self)
}
或对指针的引用。
extern int stackInit(intstack_t *&self) {
// the function remain unchanged
}
但你必须确保你实际使用的是指针!
intstack_t *stack;
stackInit(&stack); // for the reference version stackInit(stack) should be called
stackPush(stack, 1);
stackPush(stack, 2);
stackPush(stack, 3);
我试图实现我自己的堆栈程序,但是当我初始化堆栈时,我得到了分段错误!
extern int stackInit(intstack_t* self){
self = malloc(sizeof(intstack_t));
if(self == NULL){
fprintf(stderr,"Out of memory.");
free(self);
exit(-1);
}
self->bottom = malloc(MINIMUM_SIZE * sizeof(int));
if(self->bottom == NULL){
fprintf(stderr,"Out of memory.");
free(self->bottom);
exit(-1);
}
self->top = self->bottom - 1;
self->allocated_top = self->bottom + MINIMUM_SIZE -1;
return 0;
}
int main()
{
intstack_t stack;
stackInit(&stack);
stackPush(&stack, 1);
stackPush(&stack, 2);
stackPush(&stack, 3);
}
extern void stackPush(intstack_t* self, int i){
//check if the stack is full and double its size if so.
if(self->top == self->allocated_top){
ptrdiff_t total = self->top - self->bottom +1;
ptrdiff_t new_total = GROWTH_FACTOR + total;
self->bottom = realloc(self->bottom, new_total * sizeof(int));
if(self->bottom == NULL){
fprintf(stderr,"Out of memory.");
free(self->bottom);
exit(-1);
}
self->top = self->bottom + total - 1;
self->allocated_top = self->bottom + new_total - 1;
}
*(++self->top) = i;
}
这是结构:
typedef struct
{
int* bottom;
int* top;
int* allocated_top;
} intstack_t;
当我用 valgrind 编译它时,我得到了这个: 使用大小为 8 的未初始化值 ==2744731== 在 0x4008B2:stackPush(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中) ==2744731== by 0x4009AB: main (in /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack) ==2744731== 未初始化的值是由堆栈分配创建的 ==2744731== 位于 0x400987:main(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中)
==2744731== 条件跳转或移动取决于未初始化的值 ==2744731== 在 0x4007C5:stackPush(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中) ==2744731== by 0x4009AB: main (in /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack) ==2744731== 未初始化的值是由堆栈分配创建的 ==2744731== 位于 0x400987:main(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中)
==2744731== 进程以信号 11 (SIGSEGV) 的默认操作终止:转储核心 ==2744731== 地址 0x4005F4 映射区域的错误权限 ==2744731== 在 0x4008B2:stackPush(在 /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack 中) ==2744731== by 0x4009AB: main (in /vol/fob-vol2/mi16/sajoseig/Compilerbau/lab1/stack)
问题源于您声明 init 函数采用 intstack_t *
但该指针已被复制。所以基本上是将局部变量栈的地址复制到一个局部变量中,然后通过malloc
返回地址的赋值在本地覆盖,所以stack
变量保持不变(未初始化)[=16] =]
一个解决方案是修改函数以使用双指针:
extern int stackInit(intstack_t **self) {
// instead of self you write (*self)
}
或对指针的引用。
extern int stackInit(intstack_t *&self) {
// the function remain unchanged
}
但你必须确保你实际使用的是指针!
intstack_t *stack;
stackInit(&stack); // for the reference version stackInit(stack) should be called
stackPush(stack, 1);
stackPush(stack, 2);
stackPush(stack, 3);