我正在研究 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
您的程序中的错误在于您的
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);
}