Appel de la fonction WinAPI GetVolumeInformation à partir de Go pour récupérer le nom du volume de disque
Dans cet article, nous aborderons le problème rencontré lors de la tentative de appelez la fonction GetVolumeInformation depuis Go. Le but est d'obtenir le nom du volume d'un lecteur spécifié.
Pour commencer, comprenons le problème. L'extrait de code est basé sur les spécifications de la fonction GetVolumeInformation telle que définie dans l'API Windows. L'intention était de récupérer le nom du volume via le paramètre lpVolumeNameBuffer. Cependant, l'exécution de ce code a entraîné une erreur inattendue, indiquant un défaut d'accès à la mémoire.
Pour résoudre ce problème, nous devons analyser les aspects problématiques du code. Un point clé est le type unsafe.Pointer utilisé lors de la déclaration des variables pour lpVolumeNameBuffer et d'autres paramètres liés aux chaînes.
Opérations non sécurisées dans Go
Le package unsafe de Go fournit accès de bas niveau à la mémoire système sous-jacente, contournant la sécurité de type afin d'effectuer des opérations de lecture et d'écriture arbitraires. Bien que puissante, cette fonctionnalité s'accompagne d'une mise en garde concernant une corruption potentielle de la mémoire si elle est utilisée avec négligence.
Dans ce cas, l'utilisation d'unsafe.Pointer pour représenter les tampons de chaîne viole les principes de sécurité des types. Pour éviter de tels problèmes, nous pouvons utiliser les propres capacités de gestion des chaînes de Go.
Solution
Le code modifié ci-dessous adopte une approche plus sûre :
<code class="go">package main import ( "fmt" "syscall" ) func main() { var RootPathName = `C:\` var VolumeNameBuffer = make([]uint16, syscall.MAX_PATH+1) var nVolumeNameSize = uint32(len(VolumeNameBuffer)) var VolumeSerialNumber uint32 var MaximumComponentLength uint32 var FileSystemFlags uint32 var FileSystemNameBuffer = make([]uint16, 255) var nFileSystemNameSize uint32 = syscall.MAX_PATH + 1 kernel32, _ := syscall.LoadLibrary("kernel32.dll") getVolume, _ := syscall.GetProcAddress(kernel32, "GetVolumeInformationW") var nargs uintptr = 8 ret, _, callErr := syscall.Syscall9(uintptr(getVolume), nargs, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(RootPathName))), uintptr(unsafe.Pointer(&VolumeNameBuffer[0])), uintptr(nVolumeNameSize), uintptr(unsafe.Pointer(&VolumeSerialNumber)), uintptr(unsafe.Pointer(&MaximumComponentLength)), uintptr(unsafe.Pointer(&FileSystemFlags)), uintptr(unsafe.Pointer(&FileSystemNameBuffer[0])), uintptr(nFileSystemNameSize), 0) fmt.Println(ret, callErr, syscall.UTF16ToString(VolumeNameBuffer)) }</code>
Dans cette version :
En adhérant aux pratiques de sécurité de type et en utilisant la propre gestion des chaînes de Go, nous pouvons récupérer efficacement le nom du volume sans rencontrer de problèmes d'accès à la mémoire.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!