Ari Seyhun
Ari Seyhun

Reputation: 12511

Accessing a Memory Address From a String in Go?

In golang, can I print the value of a memory address from a given string?

For example, if run the following code:

a := "A String"
fmt.Println(&a)

It prints 0x1040c108.

How could I take a string such as 0x1040c108 and print the value of that string stored in the memory? Something like fmt.Println(*0x1040c108)

Is this possible?

Upvotes: 6

Views: 12737

Answers (3)

RayfenWindspear
RayfenWindspear

Reputation: 6274

This can be done, but it is a really really REALLY bad idea. Anytime you are importing the unsafe package, you are either doing something wrong, or something really hardcore. I'm hesitant to even answer this, but here goes.

https://play.golang.org/p/unkb-s8IzAo

package main

import (
    "fmt"
    "strconv"
    "unsafe"
)

func main() {
    // original example manually examined the printed address and used the value
    // updated to preserve forward compatibility due to runtime changes shifting the address over time

    hi := "HI"

    // getting address as string dynamically to preserve compatibility
    address := fmt.Sprint(&hi)

    fmt.Printf("Address of var hi: %s\n", address)

    // convert to uintptr
    var adr uint64
    adr, err := strconv.ParseUint(address, 0, 64)
    if err != nil {
        panic(err)
    }
    var ptr uintptr = uintptr(adr)

    fmt.Printf("String at address: %s\n", address)
    fmt.Printf("Value: %s\n", ptrToString(ptr))
}

func ptrToString(ptr uintptr) string {
    p := unsafe.Pointer(ptr)
    return *(*string)(p)
}

And yes, this was pretty much taken almost line for line from the unsafe godoc. https://godoc.org/unsafe

Also note that if/when your memory reference is NOT a go string, everything will come crashing down catastrophically. And that go vet is configured to send you an angry message for doing this, reinforcing that this is indeed a bad idea.

UPDATE: Updated example to run on playground as of go 1.15.1, which either the playground or go itself has changed the way the memory is addressed. Or the more likely case that changes in core libs/runtime will shift the address across versions. It now dynamically obtains the address vs a manually hardcoded value.

Upvotes: 13

Ilia Choly
Ilia Choly

Reputation: 18557

package main

import "C"

import (
    "log"
    "strconv"
    "unsafe"
)

func main() {

    // parse the string into an integer value
    addr, _ := strconv.ParseInt("0x1040c108", 0, 64)

    // cast the integer to a c string pointer
    ptr := (*C.char)(unsafe.Pointer(uintptr(addr)))

    // convert to a go string (this will segfault)
    str := C.GoString(ptr)

    // print it
    log.Println(str)
}

Upvotes: 2

Rajeev Singh
Rajeev Singh

Reputation: 3332

Yes!! you can store the address in a pointer variable and print its value by derefrencing it

i := "something"
ptr := &i
fmt.Println(*ptr)

For accessing the memory using a hard coded address such as 0x1040c108, it is necessary for your program to have access to that memory address otherwise, you will get an error saying invalid indirection of a pointer or segmentation fault.

Upvotes: 0

Related Questions