DEV Community

Shintaro Kaneko
Shintaro Kaneko

Posted on

Dangling Pointer between C and Go

In this post, I'm going to tell you about how to handle Dangling Pointer and understand the difference of behavior between C and Go.

Dangling Pointer

Dangling point is a pointer that doesn’t point to a valid object of the appropriate type. It doesn’t happen in modern programming language such as Go, Rust, etc but it usually happens in three scenarios:

  1. De-allocation: If a pointer is pointing to a memory location of an object, but the object either has been deleted or de-allocated.
  2. Function Call: If a pointer is pointing to a local variable of a function and the function call gets over.
  3. Variable goes out of scope: If a pointer is pointing to a variable that has gone out of scope.

The pointer of these scenarios is known as a dangling pointer.

Dangling pointers can lead to undefined behavior in a program, including program crashes, data corruption, or memory leaks. To avoid this, we should always set pointers to null after they are freed, and avoid using pointers that point to local variables outside the scope of their function.

Garbage Collector

Go has the Garbage Collector, and all variables that refer to an object are deleted, the object will be automatically deleted by system. However, C doesn’t have the Garbage Collector, which means programmers must handle allocated objects by themselves. If they use malloc to allocate memory dynamically, they have to take care of the memory’s scope and living period until the memory is valid.

C code

In terms of the following code, the variable r of the new_rect function is expected to be used outside the function.

#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)
Enter fullscreen mode Exit fullscreen mode

The variable r that exists in the new_rect function is deleted when the function call ends. It turns out, the function retuns an address that has already been invalid. The pointer rp points to the invalid local address and the dangling pointer error occurs.

Go code

However, in the following Go code, the variable rp in the main function points to a memory address of the variable r that is defined in the NewRect function and has NOT been deleted. So, dangling pointer error doesn’t occur.

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)
Enter fullscreen mode Exit fullscreen mode

That’s all there is.

Top comments (0)