在C和GO之间悬挂指针
#go #c #pointer #danglingpointer

在这篇文章中,我将告诉您有关如何处理悬空指针并了解C和GO之间的行为差​​异。

悬挂的指针

悬空点是指指向适当类型的有效对象的指针。它没有发生在现代编程语言中,例如GO,Rust等,但通常发生在三种情况下:

  1. 脱位:如果指针指向对象的内存位置,但是对象已被删除或取消分配。
  2. 函数调用:如果指针指向函数的局部变量,并且函数调用已经结束。
  3. 变量不在范围:如果指针指向一个超出范围的变量。

这些方案的指针被称为悬空指针。

悬挂的指针可能导致程序中的不确定行为,包括程序崩溃,数据损坏或内存泄漏。为了避免这种情况,我们应始终将指针释放后将指针设置为无效,并避免使用指向其功能范围之外的本地变量的指针。

垃圾收集器

go具有垃圾收集器,并且所有指代对象的变量均已删除,该对象将被系统自动删除。但是,C没有垃圾收集器,这意味着程序员必须自己处理分配的对象。如果他们使用malloc动态分配内存,则必须照顾记忆的范围和生活期,直到记忆有效为止。

C代码

根据以下代码,new_rect函数的变量r预计将在函数之外使用。

#include <stdio.h>

// rect represents the coordinate of rectangle.
struct rect {
    float x;
    float y;
};

// new_rect returns a reference of a variable of rect.
struct rect *new_rect(float x, float y) {
    struct rect r = {
        .x =  x,
        .y =  y,
    };
    return &r;
}

int main(int argc, char* argv[]) {
    struct rect *rp = new_rect(2.0, 3.0);
    printf("address = %p\\n", rp);
    printf(" (x, y) = (%f, %f)\\n", rp->x, rp->y);
    return 0;
}
// Output:
// address = 0x16d1c3140
//  (x, y) = (3021218960012547179075862528.00, 0.00)

当函数调用结束时,删除了new_rect函数中存在的变量r。事实证明,该功能会重新调整一个已经无效的地址。指针rp指向无效的本地地址,并发生悬空指针错误。

去代码

但是,在以下GO代码中,主要函数中的变量rp指向NewRect函数中定义的变量r的内存地址,尚未删除。因此,悬挂的指针错误不会发生。

package main

import "fmt"

// Rect represents the coordinate of rectangle.
type Rect struct {
    X float32
    Y float32
}

// NewRect returns a reference of a variable of Rect.
func NewRect(x, y float32) *Rect {
    r := Rect{
        X: x,
        Y: y,
    }
    return &r
}

func main() {
    rp := NewRect(2.0, 3.0)
    fmt.Printf("address = %p\\n", rp)
    fmt.Printf(" (x, y) = (%f, %f)\\n", rp.X, rp.Y)
}
// Output:
// address = 0x1400011c008
//  (x, y) = (1.20, 3.40)

那就是所有。