printf() 函数与我在 C 中的指针结构有一些“关系”

问题描述 投票:0回答:1

我正在研究 C 语言和内存管理的这种能力,(在本例中,我正在研究用 C 语言创建堆栈数据结构),但是当我重构我的代码时(删除无用的 printf 函数来为我指出算法)工作),我在下面的代码中删除了一个 printf 函数,我指出了它,当我重新运行我的代码时,堆栈结构中的 de 值已更改,这里的代码(某些名称在 pt_br 中,所以我'我将翻译以帮助代码理解):

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  int *arr;
  size_t size;
  unsigned int index;
}Pilha;

Pilha* criar_pilha(size_t size){ //"criar_pilha" = create_stack
  int array[size];
  Pilha* pilha_f =  malloc(sizeof(Pilha)); //"pilha_f" = stack_f
  pilha_f->size = size;
  pilha_f->arr = array;
  pilha_f->index = 0;
  return pilha_f;
}

void push_pilha(Pilha* pilha_f,int valor){ //"valor" = value
  if (!(pilha_f->size-1< pilha_f->index)) {
    pilha_f->arr[pilha_f->index] = valor;
    pilha_f->index++;
  }

}
int pop_pilha(Pilha* pilha_f){
  int valor;
  if ( (pilha_f->index-1) < 0) {
    return NULL;
  }else{
    pilha_f->index= pilha_f->index-1;
    //printf("%d",pilha_f->index);
    valor = pilha_f->arr[pilha_f->index]; 
  }
  return valor;
}

int main(){
  Pilha* nova_pilha = criar_pilha(3);// "nova_pilha" = new_stack
  int temp;
  printf("pilha criada com sucssso");// THIS FUNCTION THAT MAKES THE ERROR WHEN DELETED
  push_pilha(nova_pilha,4);
  push_pilha(nova_pilha,5);
  push_pilha(nova_pilha,72);

  temp = pop_pilha(nova_pilha);
  printf("\n%d",temp);
  temp = pop_pilha(nova_pilha);
  printf("\n%d",temp);
  temp = pop_pilha(nova_pilha);
  printf("\n%d",temp);

  free(nova_pilha);
  return 0;
}

输出:

pilha criada com sucesso

72
5
4

OBS:我创建“tmp”的原因是因为当我尝试使用“prinf(“%d”,pop_pilha(nova_pilha))直接打印时;代码抛出“分段错误” - 所以如果你能解释为什么发生这种情况我将非常感激

OBS2:当我更改 printf 函数中的内容添加“”等关键字时,上面发生的错误有一些变化 “,但是如果我更改内容字符串,问题就不会发生,除非我删除整行

删除该行后输出:

pilha criada com sucesso

72
0
0

我不知道这是否有帮助,但我使用 Archcraft (Linux) 和 gcc 13.2.1

c pointers struct stack printf
1个回答
0
投票

您的程序中的错误在于您的

criar_pilha()
函数。您创建一个在堆栈上分配的 VLA(可变长度数组)。然后让
pilha_f->arr
指向这个
array
并返回
pilha_f
,但是一旦函数返回,它在堆栈上的本地内存就会再次自动释放,并且
pilha_f->arr
指向一个无效地址。如果取消引用该指针,就会出现 UB(未定义行为),这意味着任何事情都可能发生。如果幸运的话,您的程序仍然有效。但它可能会崩溃或表现与您预期的不同。因此,您永远不应该依赖 UB。

要解决此问题,您可以通过

pilha_f->arr
malloc()
分配内存,就像您对
pilha_f
本身所做的那样。你的函数
criar_pilha()
可能看起来像这样:

Pilha* criar_pilha(size_t size) {
    // same as "sizeof(Phila)", but this way you only write the type once
    // when you use a variable instead of a type with sizeof(), you can drop the parentheses
    Pilha* pilha_f = malloc(sizeof *pilha_f);
    // remember that malloc() can return NULL on failure and dereferening it would be UB
    if (!pilha_f) {     // same as "if (pilha_f == NULL)"
        return NULL;
    }

    pilha_f->arr = malloc(sizeof *(pilha_f->arr) * size);
    // if the array could not be allocated, free the struct and return NULL
    if (!pilha_f->arr) {
        free(pilha_f);
        return NULL;
    }

    pilha_f->size = size;
    pilha_f->index = 0;

    return pilha_f;
}

由于您在堆上分别分配了结构体及其数组,因此您还需要释放它们以免泄漏任何内存。请记住以相反的顺序释放它们。您首先分配了结构体,然后分配了它的成员。释放时,首先释放成员,然后释放结构,因为如果首先释放结构,则访问其成员将是 UB。为了让用户更容易,您应该编写一个执行此操作的函数:

void free_pilha(Pilha* pilha) {
    free(pilha->arr);
    free(pilha);
}
© www.soinside.com 2019 - 2024. All rights reserved.