英文:
Accessing a Memory Address From a String in Go?
问题
在Go语言中,可以通过给定的字符串打印内存地址的值吗?
例如,如果运行以下代码:
a := "A String"
fmt.Println(&a)
它会打印出0x1040c108
。
我该如何使用类似0x1040c108
这样的字符串,并打印存储在该内存中的值?类似于fmt.Println(*0x1040c108)
这样的操作。
这种操作是否可行?
英文:
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?
答案1
得分: 13
这是可以做到的,但这是一个非常非常非常糟糕的主意。每当你导入unsafe
包时,要么你做错了什么,要么你在做一些非常核心的事情。我对于回答这个问题都有些犹豫,但还是试试吧。
package main
import (
"fmt"
"strconv"
"unsafe"
)
func main() {
// 原始示例手动检查打印的地址并使用值
// 由于运行时的更改会随着时间推移而移动地址,因此更新以保持向前兼容性
hi := "HI"
// 动态获取地址作为字符串以保持兼容性
address := fmt.Sprint(&hi)
fmt.Printf("变量 hi 的地址: %s\n", address)
// 转换为 uintptr
var adr uint64
adr, err := strconv.ParseUint(address, 0, 64)
if err != nil {
panic(err)
}
var ptr uintptr = uintptr(adr)
fmt.Printf("地址中的字符串: %s\n", address)
fmt.Printf("值: %s\n", ptrToString(ptr))
}
func ptrToString(ptr uintptr) string {
p := unsafe.Pointer(ptr)
return *(*string)(p)
}
是的,这个示例几乎是从unsafe
的godoc中逐行复制的。https://godoc.org/unsafe
还要注意,如果你的内存引用不是一个Go字符串,一切都将以灾难性的方式崩溃。而且go vet
会配置为向你发送一条愤怒的消息,因为你这样做,这再次强调了这是一个糟糕的主意。
更新:更新示例以在Go 1.15.1上运行,playground或go本身已更改了内存寻址的方式。或者更有可能的情况是核心库/运行时的更改会导致地址在不同版本之间发生变化。现在它动态获取地址而不是手动硬编码值。
英文:
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.
答案2
得分: 2
package main
import "C"
import (
"log"
"strconv"
"unsafe"
)
func main() {
// 将字符串解析为整数值
addr, _ := strconv.ParseInt("0x1040c108", 0, 64)
// 将整数转换为C字符串指针
ptr := (*C.char)(unsafe.Pointer(uintptr(addr)))
// 转换为Go字符串(这将导致段错误)
str := C.GoString(ptr)
// 打印字符串
log.Println(str)
}
这是一个Go语言的代码示例。它将一个十六进制字符串解析为整数值,然后将整数转换为C字符串指针。最后,它将C字符串指针转换为Go字符串,并打印出来。请注意,这段代码可能会导致段错误,因为它试图访问一个无效的内存地址。
英文:
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)
}
答案3
得分: 0
是的!你可以将地址存储在指针变量中,并通过解引用打印其值。
i := "something"
ptr := &i
fmt.Println(*ptr)
如果要访问一个硬编码的地址,比如 0x1040c108,你的程序必须有权限访问该内存地址,否则你将会收到一个指针无效或分段错误的错误提示。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论