当我的数组已满时,我在doublestack()函数中使用realloc()将其加倍。这样做两次以上会给我一个运行时错误。 我想这可能是因为原始堆栈(使用create()函数创建的)的大小仍然相同,所以我也加倍了,并且消除了运行时错误。
我的问题:
这是实际发生的事吗?每次数组加倍时,堆栈需要加倍?
如果是,为什么原始堆栈能够首先支持对doublestack()的第一次和第二次调用?
你能否给我一个图形/内存映射说明我们realloc()数组和堆栈时究竟发生了什么?
我在浪费任何记忆吗?有没有更好的方法来使用数组实现堆栈?
非常感谢您的光临。
CODE和OUTPUTS :(取消注释UNCOMMENT使用realloc()将堆栈大小加倍的地方
#include <stdio.h>
#include <stdlib.h>
#define INIT_CAPACITY 1
struct stack
{
int top;
int capacity;
int *array;
};
struct stack * create(int);
void push(struct stack *,int);
int top(struct stack *);
int isfull(struct stack *);
int isempty(struct stack *);
void traverse(struct stack *);
struct stack *doublestack(struct stack *);
int pop(struct stack *);
int main()
{
struct stack *S=create(INIT_CAPACITY);
push(S,1);
push(S,2);//First call to doublestack()
push(S,3);//Second call to doublestack()
push(S,4);
push(S,5);//Third call to doublestack() - ERROR
traverse(S);
}
struct stack * create(int capacity)//create a new stack with INIT_CAPACITY
{
struct stack *newstack=(struct stack *)malloc(sizeof(struct stack));
if(!newstack) return NULL;
newstack->top=-1;
newstack->capacity=capacity;
newstack->array=(int *)malloc(sizeof(int)*(newstack->capacity));
return newstack;
}
void push(struct stack *s,int data)
{
printf("\nCurrent stack is");
traverse(s);
printf("\nPushing %d onto stack:\n\n",data);
if(isfull(s))
{
printf("\nStack is FULL.Now doubling...\n\n");
doublestack(s);
}
(s->top)++;
s->array[s->top]=data;
}
struct stack * doublestack(struct stack *s)//using realloc()
{
s=realloc(s,(sizeof(struct stack)*2));//**UNCOMMENT THIS TO ELIMINATE ERROR**
s->capacity *= 2;
s->array=realloc(s->array,s->capacity);
}
void traverse(struct stack *s)
{
printf("\n");
int i;
for(i=0;i <= s->top;i++)
{
printf("%d\t",s->array[i]);
}
printf("\n\n");
}
int top(struct stack *s)
{
return s->array[s->top];
}
int isfull(struct stack *s)
{
return (s->capacity)-1==s->top;
}
int isempty(struct stack *s)
{
return s->top==-1;
}
int pop(struct stack *s)
{
if(isempty(s))
{
printf("\nStack is EMPTY\n\n");
return 0;
}
int data=s->array[s->top];
s->top--;
return data;
}
输出1 :(堆栈没有加倍,因此运行时错误)
Current stack is
Pushing 1 onto stack:
Current stack is
1
Pushing 2 onto stack:
Stack is FULL.Now doubling...
Current stack is
1 2
Pushing 3 onto stack:
Stack is FULL.Now doubling...
Current stack is
1 2 3
Pushing 4 onto stack:
Current stack is
1 2 3 4
Pushing 5 onto stack:
Stack is FULL.Now doubling...
*** glibc detected *** ./a.out: realloc(): invalid next size: 0x09191018 ***
======= Backtrace: =========
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x70f01)[0xb75e5f01]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x7660d)[0xb75eb60d]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(realloc+0xdd)[0xb75eb8ed]
./a.out[0x8048674]
./a.out[0x804861c]
./a.out[0x8048569]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb758be46]
./a.out[0x8048421]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:07 549947 /home/user/a.out
08049000-0804a000 rw-p 00000000 08:07 549947 /home/user/a.out
09191000-091b2000 rw-p 00000000 00:00 0 [heap]
b7400000-b7421000 rw-p 00000000 00:00 0
b7421000-b7500000 ---p 00000000 00:00 0
b7546000-b7562000 r-xp 00000000 08:07 548 /lib/i386-linux-gnu/libgcc_s.so.1
b7562000-b7563000 rw-p 0001b000 08:07 548 /lib/i386-linux-gnu/libgcc_s.so.1
b7574000-b7575000 rw-p 00000000 00:00 0
b7575000-b76d1000 r-xp 00000000 08:07 468 /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b76d1000-b76d2000 ---p 0015c000 08:07 468 /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b76d2000-b76d4000 r--p 0015c000 08:07 468 /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b76d4000-b76d5000 rw-p 0015e000 08:07 468 /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b76d5000-b76d8000 rw-p 00000000 00:00 0
b76e8000-b76eb000 rw-p 00000000 00:00 0
b76eb000-b76ec000 r-xp 00000000 00:00 0 [vdso]
b76ec000-b7708000 r-xp 00000000 08:07 504 /lib/i386-linux-gnu/ld-2.13.so
b7708000-b7709000 r--p 0001b000 08:07 504 /lib/i386-linux-gnu/ld-2.13.so
b7709000-b770a000 rw-p 0001c000 08:07 504 /lib/i386-linux-gnu/ld-2.13.so
bfb34000-bfb55000 rw-p 00000000 00:00 0 [stack]
Aborted
输出2 :(堆叠加倍,没有错误)
Current stack is
Pushing 1 onto stack:
Current stack is
1
Pushing 2 onto stack:
Stack is FULL.Now doubling...
Current stack is
1 2
Pushing 3 onto stack:
Current stack is
1 2 3
Pushing 4 onto stack:
Current stack is
1 2 3 4
Pushing 5 onto stack:
1 2 3 4 5
答案 0 :(得分:1)
答案 1 :(得分:1)
s->capacity
存储堆栈中的项目数。每个项目的大小为sizeof(int)
。第二个arg到realloc是字节的数量,就像malloc
一样。
s->array=realloc(s->array,s->capacity);
你想要
s->array=realloc(s->array, s->capacity * sizeof(int));
或者更一般地说
s->array = realloc(s->array, s->capacity * sizeof(*(s->array)));
此外,您应该检查realloc
的返回值并处理发生的任何错误。
这段代码是胡说八道:
s=realloc(s,(sizeof(struct stack)*2));//**UNCOMMENT THIS TO ELIMINATE ERROR**
首先,如果realloc
决定移动您的数组,则不会将新的s
返回给调用者。但更重要的是,您需要调整阵列的大小,而不是围绕它的元数据。只是巧合,取消注释该行隐藏了这个问题。
答案 2 :(得分:0)
至少,我的编译器会报告两个警告:
foo.c:40:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
foo.c:61:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
在create()
中,你永远不会真正返回新堆栈。这意味着您很快就会做一些未定义的行为。
在doublestack()
中你永远不会返回任何东西,但你也永远不会尝试使用(错过的)返回值。但是,如果realloc成功,那么前一个指针现在可能是一个无效指针,这将导致未定义的行为。