Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 12.C_malloc #11

Merged
merged 1 commit into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions 12.C_malloc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# C.malloc

```C.malloc()```は、C言語側の```malloc()```を呼び出すが、特殊仕様があり

実際にはGo側のラッパー関数が呼び出される。このラッパー関数は決してnilを返すことはない。

メモリ確保に失敗した場合は、パニックになっている。

以下、ドキュメント記載。(https://pkg.go.dev/cmd/cgo)

> As a special case, C.malloc does not call the C library malloc directly but instead calls a Go helper function that wraps the C library malloc but guarantees never to return nil. If C's malloc indicates out of memory, the helper function crashes the program, like when Go itself runs out of memory. Because C.malloc cannot fail, it has no two-result form that returns errno.

> 特殊なケースとして、C.mallocはCライブラリのmallocを直接呼び出すのではなく、CライブラリのmallocをラップするGoヘルパー関数を呼び出しますが、決してnilを返さないことが保証されています。Cのmallocがメモリ不足を示すと、Go自身がメモリ不足になったときのように、ヘルパー関数がプログラムをクラッシュさせる。C.mallocは失敗しないので、errnoを返す2つの結果形式はありません。
8 changes: 8 additions & 0 deletions 12.C_malloc/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# https://taskfile.dev

version: '3'

tasks:
default:
cmds:
- go run main.go
44 changes: 44 additions & 0 deletions 12.C_malloc/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void p(const void *v) {
char *m = (char *)v;
printf("%s\n", m);
}
*/
import "C"
import "unsafe"

func main() {
var (
bufPtr unsafe.Pointer
szBuf = C.size_t(11)
)

// malloc()を呼び出しヒープメモリを確保してもらう.
// 内部では malloc() をラップしたヘルパー関数が呼び出される.
bufPtr = C.malloc(szBuf)
defer C.free(bufPtr)

C.memset(bufPtr, C.int(0), szBuf)

//
// 文字列をコピー
//
var (
cStr = C.CString("helloworld")
cStrPtr = unsafe.Pointer(cStr)
)
defer C.free(cStrPtr)

C.memcpy(bufPtr, cStrPtr, szBuf)

//
// C側でちゃんと見れるか確認
//
C.p(bufPtr)
}