Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 716
Ari Seyhun Avatar asked May 03 '17 17:05

Ari Seyhun


People also ask

How do you get the memory address of a variable in Golang?

To get the memory address of a variable in Go or Golang, you can use the & symbol (ampersand) followed by the name of the variable you wish to get the memory address of.

How do you find address memory?

In C, we can get the memory address of any variable or member field (of struct). To do so, we use the address of (&) operator, the %p specifier to print it and a casting of (void*) on the address.

How do you value an address Go?

In Go, to print the memory address of a variable, struct, array, slice, map, or any other structure, you need to generate a pointer to the value with the address operator & and use the fmt. Println() function (or any other print function from the fmt package) to write the value address to the standard output.

What is stored at a memory address?

The memory address is the location of where the variable is stored on the computer. When we assign a value to the variable, it is stored in this memory address.


2 Answers

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.

like image 71
RayfenWindspear Avatar answered Oct 27 '22 10:10

RayfenWindspear


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)
}
like image 33
Ilia Choly Avatar answered Oct 27 '22 10:10

Ilia Choly