【问题标题】:newNode is created without returning the created node from createNode(int) function创建 newNode 时不从 createNode(int) 函数返回创建的节点
【发布时间】:2020-01-31 01:19:31
【问题描述】:

****因为我创建了一个名为 createNode(int) 的函数,它将返回一个 struct node* 类型的内存块,但我没有提到 return(temp) 仍然代码可以正常工作,如插入操作,删除工作正常,那里有堆或堆栈的概念吗?****

struct node* createNode(int data){
    struct node *temp;
    temp = (struct node*)malloc(sizeof(struct node));
    temp->data = data;
    temp->next = NULL;
    // return temp 
}
void insertNode(int position){
    struct node *temp;
    ....
    temp = createNode(data);
    ....
}

【问题讨论】:

  • 您的编译器会警告您不要从createNode() 返回值。所以使用它是未定义的行为和一些堆栈数据或寄存器只是“发生”以正确对齐,或包含仍然存在于某处的指针。
  • @WeatherVane 刚刚详细解释了它。

标签: c stack heap-memory


【解决方案1】:

这是一种未定义的行为。但我仍然会尝试解释为什么你在这里很幸运。

我在提供的代码中添加了更多代码,现在看起来像

/* test.c */
#include<stdio.h>
#include<stdlib.h>
struct node {
        int data;
        struct node* next;
};
struct node* createNode(int data){
    struct node *temp;
    temp = (struct node*)malloc(sizeof(struct node));
    temp->data = data;
    temp->next = NULL;
    // return temp
}
int main(){
    struct node *temp = createNode(12);
    printf("%d %x", temp->data);
}

编译:

$ gcc -g test.c

用 gdb 运行,这样就可以看到反汇编了

$ gdb -q ./a.out
Reading symbols from /root/a.out...done.

反汇编函数 createNode 以查看来自malloc 的返回值放置在哪里(因为这是我们将返回给main 的值)。请注意,通常保存函数返回值的 rax 包含 malloc 的返回值(这是你幸运的地方)

(gdb) disass createNode
Dump of assembler code for function createNode:
   0x0000000000400580 <+0>:     push   %rbp
   0x0000000000400581 <+1>:     mov    %rsp,%rbp
   0x0000000000400584 <+4>:     sub    $0x20,%rsp
   0x0000000000400588 <+8>:     mov    %edi,-0x14(%rbp)
   0x000000000040058b <+11>:    mov    $0x10,%edi
   0x0000000000400590 <+16>:    callq  0x400480 <malloc@plt>
   0x0000000000400595 <+21>:    mov    %rax,-0x8(%rbp)          <== rax register contains the return value of malloc, value is pushed to stack
   0x0000000000400599 <+25>:    mov    -0x8(%rbp),%rax          <== rax value retrieved from stack. now rax contains the return value of malloc
   0x000000000040059d <+29>:    mov    -0x14(%rbp),%edx
   0x00000000004005a0 <+32>:    mov    %edx,(%rax)              <== node->next assignment is done here
   0x00000000004005a2 <+34>:    mov    -0x8(%rbp),%rax          <== again rax is populated by return value of malloc
   0x00000000004005a6 <+38>:    movq   $0x0,0x8(%rax)           <== node->next is assigned to NULL here.
   0x00000000004005ae <+46>:    leaveq
   0x00000000004005af <+47>:    retq
End of assembler dump.

反汇编函数main,看看createNode是如何被调用的,以及我们从哪里得到返回值。注意 rax 值被读入 main 框架中的 temp 变量。

(gdb) disass main
Dump of assembler code for function main:
   0x00000000004005b0 <+0>:     push   %rbp
   0x00000000004005b1 <+1>:     mov    %rsp,%rbp
   0x00000000004005b4 <+4>:     sub    $0x10,%rsp
   0x00000000004005b8 <+8>:     mov    $0xc,%edi
   0x00000000004005bd <+13>:    callq  0x400580 <createNode>     <== createNode called
   0x00000000004005c2 <+18>:    mov    %rax,-0x8(%rbp)           <== rax contains the malloc's return value, so we got the correct value luckily
   0x00000000004005c6 <+22>:    mov    -0x8(%rbp),%rax
   0x00000000004005ca <+26>:    mov    (%rax),%eax
   0x00000000004005cc <+28>:    mov    %eax,%esi
   0x00000000004005ce <+30>:    mov    $0x400670,%edi
   0x00000000004005d3 <+35>:    mov    $0x0,%eax
   0x00000000004005d8 <+40>:    callq  0x400450 <printf@plt>
   0x00000000004005dd <+45>:    leaveq
   0x00000000004005de <+46>:    retq
End of assembler dump.
(gdb) q

我希望这能解释为什么我们在 temp 中看到正确的值,即使 createNode 中没有 return 语句。

【讨论】:

  • 如果它看起来正确并解释行为,请接受答案
  • 我认为你解释得很好兄弟,但问题是我不懂汇编语言。那为什么我不明白你写的汇编代码所以请告诉我该怎么做。跨度>
  • 你的程序集不是我写的。它是对已编译代码的反汇编。参加课程/阅读有关微控制器或微处理器的书籍以了解更多信息。从 8051 或 8086 开始
  • 先生,请向我推荐任何好书或视频资料,我可以更深入地学习这些概念。
猜你喜欢
  • 2012-10-25
  • 1970-01-01
  • 2011-09-10
  • 1970-01-01
  • 2018-05-07
  • 2020-11-12
  • 1970-01-01
  • 2013-03-22
  • 2021-09-27
相关资源
最近更新 更多