指针在printf之后更改值 [英] Pointer changes value after printf

查看:109
本文介绍了指针在printf之后更改值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以今天我试图用C实现简单的堆栈,但是遇到了以下问题,我无法解决或解释为什么发生。

So today I was trying to implement simple stack in C, but I have encountered following issue that I can't resolve or explain why is happening.

#include<stdio.h>

typedef struct stack_element stack_element;
typedef struct stack stack;

struct stack_element
{
    void* data;
    stack_element* next;
};

struct stack
{
    stack_element* top;
    int size;
    int max_size;
};

void push(stack* this, stack_element to_add)
{
    if(this->top == NULL)
    {
        this->top = &to_add;
        this->top->next = this->top;
        printf("%p\n", this->top);
        printf("%p\n", this->top->next);
        printf("First\n");
        return;
    }
}

void debug(stack* this)
{
    if(this->top == NULL) return;
    printf("Sample 1 %p\n", this->top);
    printf("Sample 2 %p\n\n", this->top->next);
}

int main()
{
    stack_element* tmp = malloc(sizeof(stack_element));
    stack* st = malloc(sizeof(stack)); 
    tmp->data = 1;
    push(st, *tmp);
    printf("Sample 1 %p\n", st->top);
    printf("Sample 2 %p\n\n", st->top->next);
    debug(st);
    printf("Sample 1 %p\n", st->top);
    printf("Sample 2 %p\n\n", st->top->next);
    printf("END\n");
    return 0;
}

上面的代码给出了一些奇怪的结果,如果我更换编译器,结果也会不同。

Code above gives some strange results, and also different ones if I change compiler.

我尝试过的第一个编译器是gcc,它给出以下输出:

First compiler I've tried is gcc and it gives following output:

0x7ffd6d96d3b0
0x7ffd6d96d3b0
First
Sample 1 0x7ffd6d96d3b0
Sample 2 0x7ffd6d96d3b0

Sample 1 0x7ffd6d96d3b0
Sample 2 0x400670

Sample 1 0x7ffd6d96d3b0
Sample 2 0x40068d

END

第二个结果来自c:

0x7ffd6d05fb30
0x7ffd6d05fb30
First
Sample 1 0x7ffd6d05fb30
Sample 2 0x7ffd6d05fb30

Sample 1 0x7ffd6d05fb30
Sample 2 0x2042030

Sample 1 0x7ffd6d05fb30
Sample 2 0x2042030

END

我的第一个问题是为什么当我从无效位置打印时,示例2甚至会发生变化调试吗?我也试图注释掉调试函数调用和结果ar e也很奇怪。在gcc中,样本均符合预期,但在clang中,样本2没有明显的原因存在差异。

My first question is why is Sample 2 even changing when I printf it from void debug? Also I have tried to comment out debug function call and results are also strange. In gcc samples are as expected all are matching, but in clang there is difference in sample 2 for no obvious reason.

我的第二个问题是为什么甚至

希望我已经发布了有关我所遇到的问题的足够信息,如果没有在评论中写信给我,以发布更多信息。

Hope I have posted enough information about the issue I am having, if not write me in comment to post more information.

推荐答案

您的 push 函数按值采用第二个参数,因此它会创建 struct stack_element 的本地副本。这意味着 this-> top =& to_add; 行将指针 top 重定向为指向局部变量(具有自动存储期限)。函数 push 结束后,变量的生存期结束,将 top 更改为悬空指针。因此,取消引用 this-> top-> next (和 st-> top-> next )调用未定义的行为

Your push function takes the second parameter by value, so it creates a local copy of the struct stack_element. That means the line this->top = &to_add; redirects the pointer top to point at a local variable (with automatic storage duration). After the function push ends that variable's lifetime ends, changing top into a dangling pointer. Thus the dereferencing this->top->next (and st->top->next) invoke undefined behavior.

您最想做的是为 push 作为指针: void push(stack * this,stack_element * to_add)并更改行:

What you most likely intended to do was take the second parameter for push as a pointer: void push(stack* this, stack_element* to_add) and change the line:

this->top = &to_add;

this->top = to_add;

注意:您建议在内部使用 malloc push 是另一种可能性,但是可能会产生不清楚的代码,因为这将要求调用者知道 top 需要免费 d以避免内存泄漏。另外,您还可以提供一个析构函数函数,该函数负责所有内存管理,将其隐藏在调用者面前。

NOTE: Your suggestion of using malloc inside push is another possibility, however that might create unclear code, as it would require the caller to know that top needs to be freed in order to avoid memory leaks. Alternatively you could also provide a "destructor" function which would take care of all memory management, hiding it from the caller.

这篇关于指针在printf之后更改值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆