Dynamically allocating memory (in C)动态分配内存的问题

huangapple go评论59阅读模式
英文:

Problems dynamically allocating memory (in C)

问题

我理解了您的请求,以下是您提供的代码的翻译:

我正在学习数据结构。所以我决定使用数组自己实现一个栈。问题是,当程序尝试在栈满时推入一个元素时会出现问题。我的想法是使用realloc()重新分配数组的现有指针,我之前使用malloc()手动分配内存以增加栈的大小,然后推入相应的项目。在运行valgrind代码后,它显示错误:“Invalid write of size 4 ... 4 bytes before a block of size 16 alloc'd”。
需要注意的是我是一个初学者,所以任何帮助都会很感激。

typedef struct {
    int *v;
    int cap;
    int sz;
} stack;

stack* build(){
    stack *new = (stack*) malloc(sizeof(stack));
    new->v = (int*) malloc(sizeof(int) * 4);
    new->cap = 4;
    new->sz = 0;
    return new;
}

int is_empty(stack *s){
    return s->sz == 0;
}

int push(stack *s, int e)
{
    int success = 1;

    if (s->sz == s->cap){
        int *tmp = (int*) realloc(s->v, (s->cap + 1) * sizeof(int));
        if ((success = tmp != NULL)){
            s->v = tmp;
            ++s->cap;
        }
    }

    if (success){
        s->v
展开收缩
= e;
} return success; } int top(stack *s){ return *(s->v); } int pop(stack *s){ int value; if (is_empty(s)) return -1; value = *(s->v); s->v--; s->sz--; return value; } void destroy(stack *s){ s->v -= s->sz + 1; free(s->v); free(s); } int match(char p1, char p2){ if (p1 == '(') return (p1 - p2) == '(' - ')'; else if (p1 == '[') return (p1 - p2) == '[' - ']'; else return (p1 - p2) == '{' - '}'; } int main(){ int c; stack *s = build(); while ((c = getchar()) != EOF && c != '\n'){ if (c == '(' || c == '[' || c == '{') push(s, c); else if (c == ')' || c == ']' || c == '}'){ if (!match(pop(s), c)){ printf("no\n"); destroy(s); return 0; } } } puts((is_empty(s)) ? "yes" : "no"); destroy(s); return 0; }

希望这个翻译对您有所帮助。如果您有其他问题,请随时提问。

英文:

I am studying data structures. So I decided to implement a stack by myself using arrays. The problem is when the program tries to push an element when the stacks is full. My idea was to realloc() the existing pointer to the array, which I previously manually alocated memory with malloc() to increase the size of the stack by 1 then push the respective Item. After running the code on valgrind it shows me the error: "Invalid write of size4 ... 4 bytes before a block of size 16 alloc'd ".
Noting that I am a beginner so any help is appreciated.

typedef struct {
int *v;    
int cap;    
int sz;
} stack;
stack* build(){
stack *new = (stack*) malloc(sizeof(stack));
new->v = (int*) malloc(sizeof(int) * 4);
new->cap = 4;
new->sz = 0;
return new;
}
int is_empty(stack *s){
return s->sz == 0;
}
int push( stack *s, int e )
{
int success = 1;
if (s->sz == s->cap){
int*tmp =(int*)realloc(s->v,(s->cap+1)*sizeof( int));
if (( success = tmp != NULL )){
s->v = tmp;
++s->cap;
}
}
if (success){
s->v[s->sz++] = e;
}
return success;
}
int top(stack *s){
return *(s->v);
}
int pop(stack *s){
int value;
if(is_empty(s))
return -1;
value = *(s->v);
s->v--;
s->sz--;
return value;   
}
void destroy(stack *s){
s->v -= s->sz + 1;
free(s->v);
free(s);
}
int match(char p1, char p2){
if(p1 == '(')
return (p1 - p2) == '(' - ')';
else if(p1 == '[')
return (p1 - p2) == '[' - ']';
else
return (p1 - p2) == '{' - '}';
}
int main(){
int c;
stack *s = build();
while((c = getchar()) != EOF && c != '\n'){
if(c == '(' || c == '[' || c == '{')
push(s, c);
else if(c == ')' || c == ']' || c == '}'){
if(!match(pop(s), c)){
printf("no\n");
destroy(s);
return 0;
}
}
}
puts((is_empty(s)) ? "yes" : "no");
destroy(s);
return 0;
}

答案1

得分: 1

这是您要翻译的代码部分:

This call of `realloc`

    s->v = (int*) realloc(s->v + 1 - s->sz, sizeof(int) * (s->cap + 1));

is incorrect. The first argument of the function shall be the original pointer that points to the previously allocated memory or NULL.

Also this check within the function `push`

    if(is_empty(s))
        *(s->v) = e;

is redundant.

The function can look the following way. Pay attention that the function should not issue any message. It is the caller of the function that will decide whether to output a message depending on whether a new item was added successfully or not.

int push( stack *s, int e )
{
    int success = 1;

    if ( s->sz == s->cap )
    {
        int *tmp = realloc( s->v, ( s->cap + 1 ) * sizeof( int ) );

        if ( ( success = tmp != NULL ) )
        {
            s->v = tmp;
            ++s->cap;
        }
    }

    if ( success )
    {          
        s->v
展开收缩
= e;
} return success; } Here is a demonstration program that shows the usage of the function `push`. #include <stdio.h> #include <stdlib.h> typedef struct { int *v; int cap; int sz; } stack; /* In case this is how I innitialize an array: */ stack *build() { stack *new = ( stack * )malloc( sizeof( stack ) ); new->v = ( int * )malloc( sizeof( int ) * 4 ); new->cap = 4; new->sz = 0; return new; } int push( stack *s, int e ) { int success = 1; if (s->sz == s->cap) { int *tmp = ( int * )realloc( s->v, ( s->cap + 1 ) * sizeof( int ) ); if (( success = tmp != NULL )) { s->v = tmp; ++s->cap; } } if (success) { s->v
展开收缩
= e;
} return success; } int main( void ) { stack *s = build(); for (int i = 0; i < 10; i++) { if (!push( s, i )) { puts( "Error: not enough memory." ); } } for (int i = s->sz; i != 0; ) { printf( "%d ", s->v[--i] ); } putchar( '\n' ); }
英文:

This call of realloc

s-&gt;v = (int*) realloc(s-&gt;v + 1 - s-&gt;sz, sizeof(int) * (s-&gt;cap + 1));

is incorrect. The first argument of the function shall be the original pointer that points to the previously allocated memory or NULL.

Also this check within the function push

if(is_empty(s))
*(s-&gt;v) = e;

is redundant.

The function can look the following way. Pay attention that the function should not issue any message. It is the caller of the function that will decide whether to output a message depending on whether a new item was added successfully or not.

int push( stack *s, int e )
{
int success = 1;
if ( s-&gt;sz == s-&gt;cap )
{
int *tmp = realloc( s-&gt;v, ( s-&gt;cap + 1 ) * sizeof( int ) );
if ( ( success = tmp != NULL ) )
{
s-&gt;v = tmp;
++s-&gt;cap;
}
}
if ( success )
{          
s-&gt;v[s-&gt;sz++] = e;
}
return success;
}

Here is a demonstration program that shows the usage of the function push.

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
typedef struct {
int *v;
int cap;
int sz;
} stack; 
/* In case this is how I innitialize an array: */
stack *build() {
stack *new = ( stack * )malloc( sizeof( stack ) );
new-&gt;v = ( int * )malloc( sizeof( int ) * 4 );
new-&gt;cap = 4;
new-&gt;sz = 0;
return new;
}
int push( stack *s, int e )
{
int success = 1;
if (s-&gt;sz == s-&gt;cap)
{
int *tmp = ( int * )realloc( s-&gt;v, ( s-&gt;cap + 1 ) * sizeof( int ) );
if (( success = tmp != NULL ))
{
s-&gt;v = tmp;
++s-&gt;cap;
}
}
if (success)
{
s-&gt;v[s-&gt;sz++] = e;
}
return success;
}
int main( void )
{
stack *s = build();
for (int i = 0; i &lt; 10; i++)
{
if (!push( s, i ))
{
puts( &quot;Error: not enough memory.&quot; );
}
}
for (int i = s-&gt;sz; i != 0; )
{
printf( &quot;%d &quot;, s-&gt;v[--i] );
}
putchar( &#39;\n&#39; );
}

The program output is

9 8 7 6 5 4 3 2 1 0

Of course you will need to write yourself a function that will free all the allocated memory.

Pay attention to that it is better to define the stack as a singly-linked list.

huangapple
  • 本文由 发表于 2023年3月31日 03:03:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75892049.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定