Merge pull request #394 from libgit2/cmn/keepalive-all-the-things-v26

KeepAlive all the things for v26
diff --git a/blame.go b/blame.go
index b07d6bc..de32bb3 100644
--- a/blame.go
+++ b/blame.go
@@ -76,6 +76,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_blame_file(&blamePtr, v.ptr, cpath, copts)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -88,11 +89,15 @@
 }
 
 func (blame *Blame) HunkCount() int {
-	return int(C.git_blame_get_hunk_count(blame.ptr))
+	ret := int(C.git_blame_get_hunk_count(blame.ptr))
+	runtime.KeepAlive(blame)
+
+	return ret
 }
 
 func (blame *Blame) HunkByIndex(index int) (BlameHunk, error) {
 	ptr := C.git_blame_get_hunk_byindex(blame.ptr, C.uint32_t(index))
+	runtime.KeepAlive(blame)
 	if ptr == nil {
 		return BlameHunk{}, ErrInvalid
 	}
@@ -101,6 +106,7 @@
 
 func (blame *Blame) HunkByLine(lineno int) (BlameHunk, error) {
 	ptr := C.git_blame_get_hunk_byline(blame.ptr, C.size_t(lineno))
+	runtime.KeepAlive(blame)
 	if ptr == nil {
 		return BlameHunk{}, ErrInvalid
 	}
diff --git a/blob.go b/blob.go
index 73a4a19..5235597 100644
--- a/blob.go
+++ b/blob.go
@@ -21,13 +21,19 @@
 }
 
 func (v *Blob) Size() int64 {
-	return int64(C.git_blob_rawsize(v.cast_ptr))
+	ret := int64(C.git_blob_rawsize(v.cast_ptr))
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Blob) Contents() []byte {
 	size := C.int(C.git_blob_rawsize(v.cast_ptr))
 	buffer := unsafe.Pointer(C.git_blob_rawcontent(v.cast_ptr))
-	return C.GoBytes(buffer, size)
+
+	goBytes := C.GoBytes(buffer, size)
+	runtime.KeepAlive(v)
+
+	return goBytes
 }
 
 func (repo *Repository) CreateBlobFromBuffer(data []byte) (*Oid, error) {
@@ -53,6 +59,7 @@
 	}
 
 	ecode := C.git_blob_create_frombuffer(&id, repo.ptr, unsafe.Pointer(&data[0]), size)
+	runtime.KeepAlive(repo)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -102,16 +109,18 @@
 		return nil, MakeGitError(ecode)
 	}
 
-	return newBlobWriteStreamFromC(stream), nil
+	return newBlobWriteStreamFromC(stream, repo), nil
 }
 
 type BlobWriteStream struct {
-	ptr *C.git_writestream
+	ptr  *C.git_writestream
+	repo *Repository
 }
 
-func newBlobWriteStreamFromC(ptr *C.git_writestream) *BlobWriteStream {
+func newBlobWriteStreamFromC(ptr *C.git_writestream, repo *Repository) *BlobWriteStream {
 	stream := &BlobWriteStream{
-		ptr: ptr,
+		ptr:  ptr,
+		repo: repo,
 	}
 
 	runtime.SetFinalizer(stream, (*BlobWriteStream).Free)
@@ -128,6 +137,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C._go_git_writestream_write(stream.ptr, ptr, size)
+	runtime.KeepAlive(stream)
 	if ecode < 0 {
 		return 0, MakeGitError(ecode)
 	}
@@ -147,6 +157,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_blob_create_fromstream_commit(&oid, stream.ptr)
+	runtime.KeepAlive(stream)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
diff --git a/branch.go b/branch.go
index d381c23..d6e7a53 100644
--- a/branch.go
+++ b/branch.go
@@ -88,6 +88,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_branch_iterator_new(&ptr, repo.ptr, refType)
+	runtime.KeepAlive(repo)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -106,6 +107,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_create(&ptr, repo.ptr, cBranchName, target.cast_ptr, cForce)
+	runtime.KeepAlive(repo)
+	runtime.KeepAlive(target)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -117,6 +120,7 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 	ret := C.git_branch_delete(b.Reference.ptr)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -133,6 +137,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_move(&ptr, b.Reference.ptr, cNewBranchName, cForce)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -145,6 +150,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_is_head(b.Reference.ptr)
+	runtime.KeepAlive(b.Reference)
 	switch ret {
 	case 1:
 		return true, nil
@@ -165,6 +171,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_lookup(&ptr, repo.ptr, cName, C.git_branch_t(bt))
+	runtime.KeepAlive(repo)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -179,6 +186,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_name(&cName, b.Reference.ptr)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
@@ -196,6 +204,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_remote_name(&nameBuf, repo.ptr, cName)
+	runtime.KeepAlive(repo)
 	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
@@ -212,6 +221,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_set_upstream(b.Reference.ptr, cName)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -225,6 +235,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_upstream(&ptr, b.Reference.ptr)
+	runtime.KeepAlive(b.Reference)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -241,6 +252,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_branch_upstream_name(&nameBuf, repo.ptr, cName)
+	runtime.KeepAlive(repo)
 	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
diff --git a/checkout.go b/checkout.go
index f5822c9..db3118f 100644
--- a/checkout.go
+++ b/checkout.go
@@ -188,6 +188,7 @@
 	defer freeCheckoutOpts(cOpts)
 
 	ret := C.git_checkout_head(v.ptr, cOpts)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -211,6 +212,7 @@
 	defer freeCheckoutOpts(cOpts)
 
 	ret := C.git_checkout_index(v.ptr, iptr, cOpts)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -226,6 +228,7 @@
 	defer freeCheckoutOpts(cOpts)
 
 	ret := C.git_checkout_tree(v.ptr, tree.ptr, cOpts)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
diff --git a/cherrypick.go b/cherrypick.go
index afc1b7e..8983a7a 100644
--- a/cherrypick.go
+++ b/cherrypick.go
@@ -66,6 +66,8 @@
 	defer freeCherrypickOpts(cOpts)
 
 	ecode := C.git_cherrypick(v.ptr, commit.cast_ptr, cOpts)
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(commit)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
diff --git a/commit.go b/commit.go
index fc2815a..ba7dcaa 100644
--- a/commit.go
+++ b/commit.go
@@ -35,16 +35,18 @@
 	defer C.git_buf_free(&c_signature)
 
 	oid := c.Id()
-	
 	repo := C.git_commit_owner(c.cast_ptr)
+
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
 	ret := C.git_commit_extract_signature(&c_signature, &c_signed, repo, oid.toC(), nil)
-	
+
 	if ret < 0 {
-		return "", "", MakeGitError(ret) 
+		return "", "", MakeGitError(ret)
 	} else {
 		return C.GoString(c_signature.ptr), C.GoString(c_signed.ptr), nil
 	}
-	
+
 }
 
 func (c Commit) Summary() string {
@@ -86,15 +88,21 @@
 		return nil
 	}
 
-	return allocCommit(cobj, c.repo)
+	parent := allocCommit(cobj, c.repo)
+	runtime.KeepAlive(c)
+	return parent
 }
 
 func (c *Commit) ParentId(n uint) *Oid {
-	return newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n)))
+	ret := newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n)))
+	runtime.KeepAlive(c)
+	return ret
 }
 
 func (c *Commit) ParentCount() uint {
-	return uint(C.git_commit_parentcount(c.cast_ptr))
+	ret := uint(C.git_commit_parentcount(c.cast_ptr))
+	runtime.KeepAlive(c)
+	return ret
 }
 
 func (c *Commit) Amend(refname string, author, committer *Signature, message string, tree *Tree) (*Oid, error) {
@@ -127,6 +135,9 @@
 	oid := new(Oid)
 
 	cerr := C.git_commit_amend(oid.toC(), c.cast_ptr, cref, authorSig, committerSig, nil, cmsg, tree.cast_ptr)
+	runtime.KeepAlive(oid)
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(tree)
 	if cerr < 0 {
 		return nil, MakeGitError(cerr)
 	}
diff --git a/config.go b/config.go
index 7408fbc..c19ad32 100644
--- a/config.go
+++ b/config.go
@@ -78,6 +78,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_add_file_ondisk(c.ptr, cpath, C.git_config_level_t(level), cbool(force))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -94,6 +95,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_get_int32(&out, c.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return 0, MakeGitError(ret)
 	}
@@ -110,6 +112,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_get_int64(&out, c.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return 0, MakeGitError(ret)
 	}
@@ -126,7 +129,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname); ret < 0 {
+	ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname)
+	runtime.KeepAlive(c)
+	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
 	defer C.git_buf_free(&valBuf)
@@ -143,6 +148,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_get_bool(&out, c.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -162,7 +168,7 @@
 		defer C.free(unsafe.Pointer(cregexp))
 	}
 
-	iter := new(ConfigIterator)
+	iter := &ConfigIterator{cfg: c}
 
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
@@ -179,7 +185,7 @@
 // NewIterator creates an iterator over each entry in the
 // configuration
 func (c *Config) NewIterator() (*ConfigIterator, error) {
-	iter := new(ConfigIterator)
+	iter := &ConfigIterator{cfg: c}
 
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
@@ -195,7 +201,7 @@
 // NewIteratorGlob creates an iterator over each entry in the
 // configuration whose name matches the given regular expression
 func (c *Config) NewIteratorGlob(regexp string) (*ConfigIterator, error) {
-	iter := new(ConfigIterator)
+	iter := &ConfigIterator{cfg: c}
 	cregexp := C.CString(regexp)
 	defer C.free(unsafe.Pointer(cregexp))
 
@@ -221,6 +227,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_string(c.ptr, cname, cvalue)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -241,6 +248,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_int32(c.ptr, cname, C.int32_t(value))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -256,6 +264,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_int64(c.ptr, cname, C.int64_t(value))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -271,6 +280,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_bool(c.ptr, cname, cbool(value))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -292,6 +302,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_set_multivar(c.ptr, cname, cregexp, cvalue)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -307,7 +318,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_delete_entry(c.ptr, cname)
-
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -323,6 +334,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_config_open_level(&config.ptr, parent.ptr, C.git_config_level_t(level))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(parent)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -349,6 +362,7 @@
 
 type ConfigIterator struct {
 	ptr *C.git_config_iterator
+	cfg *Config
 }
 
 // Next returns the next entry for this iterator
@@ -363,7 +377,10 @@
 		return nil, MakeGitError(ret)
 	}
 
-	return newConfigEntryFromC(centry), nil
+	entry := newConfigEntryFromC(centry)
+	runtime.KeepAlive(iter)
+
+	return entry, nil
 }
 
 func (iter *ConfigIterator) Free() {
diff --git a/describe.go b/describe.go
index d75dbcb..0b75076 100644
--- a/describe.go
+++ b/describe.go
@@ -128,6 +128,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_describe_commit(&resultPtr, c.ptr, cDescribeOpts)
+	runtime.KeepAlive(c)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -162,6 +163,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_describe_workdir(&resultPtr, repo.ptr, cDescribeOpts)
+	runtime.KeepAlive(repo)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -206,6 +208,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_describe_format(&resultBuf, result.ptr, cFormatOpts)
+	runtime.KeepAlive(result)
 	if ecode < 0 {
 		return "", MakeGitError(ecode)
 	}
diff --git a/diff.go b/diff.go
index e8d5007..3cc1dc2 100644
--- a/diff.go
+++ b/diff.go
@@ -127,14 +127,17 @@
 }
 
 type Diff struct {
-	ptr *C.git_diff
+	ptr  *C.git_diff
+	repo *Repository
 }
 
 func (diff *Diff) NumDeltas() (int, error) {
 	if diff.ptr == nil {
 		return -1, ErrInvalid
 	}
-	return int(C.git_diff_num_deltas(diff.ptr)), nil
+	ret := int(C.git_diff_num_deltas(diff.ptr))
+	runtime.KeepAlive(diff)
+	return ret, nil
 }
 
 func (diff *Diff) GetDelta(index int) (DiffDelta, error) {
@@ -142,16 +145,19 @@
 		return DiffDelta{}, ErrInvalid
 	}
 	ptr := C.git_diff_get_delta(diff.ptr, C.size_t(index))
-	return diffDeltaFromC(ptr), nil
+	ret := diffDeltaFromC(ptr)
+	runtime.KeepAlive(diff)
+	return ret, nil
 }
 
-func newDiffFromC(ptr *C.git_diff) *Diff {
+func newDiffFromC(ptr *C.git_diff, repo *Repository) *Diff {
 	if ptr == nil {
 		return nil
 	}
 
 	diff := &Diff{
-		ptr: ptr,
+		ptr:  ptr,
+		repo: repo,
 	}
 
 	runtime.SetFinalizer(diff, (*Diff).Free)
@@ -187,6 +193,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_diff_find_similar(diff.ptr, copts)
+	runtime.KeepAlive(diff)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -209,15 +216,21 @@
 }
 
 func (stats *DiffStats) Insertions() int {
-	return int(C.git_diff_stats_insertions(stats.ptr))
+	ret := int(C.git_diff_stats_insertions(stats.ptr))
+	runtime.KeepAlive(stats)
+	return ret
 }
 
 func (stats *DiffStats) Deletions() int {
-	return int(C.git_diff_stats_deletions(stats.ptr))
+	ret := int(C.git_diff_stats_deletions(stats.ptr))
+	runtime.KeepAlive(stats)
+	return ret
 }
 
 func (stats *DiffStats) FilesChanged() int {
-	return int(C.git_diff_stats_files_changed(stats.ptr))
+	ret := int(C.git_diff_stats_files_changed(stats.ptr))
+	runtime.KeepAlive(stats)
+	return ret
 }
 
 type DiffStatsFormat int
@@ -240,6 +253,7 @@
 
 	ret := C.git_diff_stats_to_buf(&buf,
 		stats.ptr, C.git_diff_stats_format_t(format), C.size_t(width))
+	runtime.KeepAlive(stats)
 	if ret < 0 {
 		return "", MakeGitError(ret)
 	}
@@ -253,7 +267,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ecode := C.git_diff_get_stats(&stats.ptr, diff.ptr); ecode < 0 {
+	ecode := C.git_diff_get_stats(&stats.ptr, diff.ptr)
+	runtime.KeepAlive(diff)
+	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
 	runtime.SetFinalizer(stats, (*DiffStats).Free)
@@ -301,6 +317,7 @@
 	defer pointerHandles.Untrack(handle)
 
 	ecode := C._go_git_diff_foreach(diff.ptr, 1, intHunks, intLines, handle)
+	runtime.KeepAlive(diff)
 	if ecode < 0 {
 		return data.Error
 	}
@@ -380,6 +397,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_patch_from_diff(&patchPtr, diff.ptr, C.size_t(deltaIndex))
+	runtime.KeepAlive(diff)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -537,7 +555,7 @@
 
 	if data != nil {
 		if data.Diff == nil {
-			data.Diff = newDiffFromC(diff_so_far)
+			data.Diff = newDiffFromC(diff_so_far, nil)
 		}
 
 		err := data.Callback(data.Diff, diffDeltaFromC(delta_to_add), C.GoString(matched_pathspec))
@@ -618,6 +636,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_diff_tree_to_tree(&diffPtr, v.ptr, oldPtr, newPtr, copts)
+	runtime.KeepAlive(oldTree)
+	runtime.KeepAlive(newTree)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -625,7 +645,7 @@
 	if notifyData != nil && notifyData.Diff != nil {
 		return notifyData.Diff, nil
 	}
-	return newDiffFromC(diffPtr), nil
+	return newDiffFromC(diffPtr, v), nil
 }
 
 func (v *Repository) DiffTreeToWorkdir(oldTree *Tree, opts *DiffOptions) (*Diff, error) {
@@ -643,6 +663,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_diff_tree_to_workdir(&diffPtr, v.ptr, oldPtr, copts)
+	runtime.KeepAlive(oldTree)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -650,7 +671,7 @@
 	if notifyData != nil && notifyData.Diff != nil {
 		return notifyData.Diff, nil
 	}
-	return newDiffFromC(diffPtr), nil
+	return newDiffFromC(diffPtr, v), nil
 }
 
 func (v *Repository) DiffTreeToIndex(oldTree *Tree, index *Index, opts *DiffOptions) (*Diff, error) {
@@ -673,6 +694,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_diff_tree_to_index(&diffPtr, v.ptr, oldPtr, indexPtr, copts)
+	runtime.KeepAlive(oldTree)
+	runtime.KeepAlive(index)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -680,7 +703,7 @@
 	if notifyData != nil && notifyData.Diff != nil {
 		return notifyData.Diff, nil
 	}
-	return newDiffFromC(diffPtr), nil
+	return newDiffFromC(diffPtr, v), nil
 }
 
 func (v *Repository) DiffTreeToWorkdirWithIndex(oldTree *Tree, opts *DiffOptions) (*Diff, error) {
@@ -698,6 +721,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_diff_tree_to_workdir_with_index(&diffPtr, v.ptr, oldPtr, copts)
+	runtime.KeepAlive(oldTree)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -705,7 +729,7 @@
 	if notifyData != nil && notifyData.Diff != nil {
 		return notifyData.Diff, nil
 	}
-	return newDiffFromC(diffPtr), nil
+	return newDiffFromC(diffPtr, v), nil
 }
 
 func (v *Repository) DiffIndexToWorkdir(index *Index, opts *DiffOptions) (*Diff, error) {
@@ -723,6 +747,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_diff_index_to_workdir(&diffPtr, v.ptr, indexPtr, copts)
+	runtime.KeepAlive(index)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -730,7 +755,7 @@
 	if notifyData != nil && notifyData.Diff != nil {
 		return notifyData.Diff, nil
 	}
-	return newDiffFromC(diffPtr), nil
+	return newDiffFromC(diffPtr, v), nil
 }
 
 // DiffBlobs performs a diff between two arbitrary blobs. You can pass
@@ -773,6 +798,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C._go_git_diff_blobs(oldBlobPtr, oldBlobPath, newBlobPtr, newBlobPath, copts, 1, intHunks, intLines, handle)
+	runtime.KeepAlive(oldBlob)
+	runtime.KeepAlive(newBlob)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
diff --git a/git.go b/git.go
index 5181b8b..0925e45 100644
--- a/git.go
+++ b/git.go
@@ -232,6 +232,7 @@
 			return int(ret), MakeGitError(ret)
 		}
 	}
+	runtime.KeepAlive(ids)
 	return int(ret), nil
 }
 
diff --git a/graph.go b/graph.go
index e5d7732..688818c 100644
--- a/graph.go
+++ b/graph.go
@@ -13,6 +13,9 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_graph_descendant_of(repo.ptr, commit.toC(), ancestor.toC())
+	runtime.KeepAlive(repo)
+	runtime.KeepAlive(commit)
+	runtime.KeepAlive(ancestor)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -28,6 +31,9 @@
 	var behindT C.size_t
 
 	ret := C.git_graph_ahead_behind(&aheadT, &behindT, repo.ptr, local.toC(), upstream.toC())
+	runtime.KeepAlive(repo)
+	runtime.KeepAlive(local)
+	runtime.KeepAlive(upstream)
 	if ret < 0 {
 		return 0, 0, MakeGitError(ret)
 	}
diff --git a/ignore.go b/ignore.go
index 6b12348..c698de1 100644
--- a/ignore.go
+++ b/ignore.go
@@ -17,6 +17,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_ignore_add_rule(v.ptr, crules)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -28,6 +29,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_ignore_clear_internal_rules(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -44,6 +46,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_ignore_path_is_ignored(&ignored, v.ptr, cpath)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
diff --git a/index.go b/index.go
index 2afdcdf..5106516 100644
--- a/index.go
+++ b/index.go
@@ -45,7 +45,8 @@
 )
 
 type Index struct {
-	ptr *C.git_index
+	ptr  *C.git_index
+	repo *Repository
 }
 
 type IndexTime struct {
@@ -97,8 +98,8 @@
 	C.free(unsafe.Pointer(entry.path))
 }
 
-func newIndexFromC(ptr *C.git_index) *Index {
-	idx := &Index{ptr}
+func newIndexFromC(ptr *C.git_index, repo *Repository) *Index {
+	idx := &Index{ptr, repo}
 	runtime.SetFinalizer(idx, (*Index).Free)
 	return idx
 }
@@ -115,7 +116,7 @@
 		return nil, MakeGitError(err)
 	}
 
-	return newIndexFromC(ptr), nil
+	return newIndexFromC(ptr, nil), nil
 }
 
 // OpenIndex creates a new index at the given path. If the file does
@@ -133,13 +134,15 @@
 		return nil, MakeGitError(err)
 	}
 
-	return newIndexFromC(ptr), nil
+	return newIndexFromC(ptr, nil), nil
 }
 
 // Path returns the index' path on disk or an empty string if it
 // exists only in memory.
 func (v *Index) Path() string {
-	return C.GoString(C.git_index_path(v.ptr))
+	ret := C.GoString(C.git_index_path(v.ptr))
+	runtime.KeepAlive(v)
+	return ret
 }
 
 // Add adds or replaces the given entry to the index, making a copy of
@@ -153,7 +156,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if err := C.git_index_add(v.ptr, &centry); err < 0 {
+	err := C.git_index_add(v.ptr, &centry)
+	runtime.KeepAlive(v)
+	if err < 0 {
 		return MakeGitError(err)
 	}
 
@@ -168,6 +173,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_index_add_bypath(v.ptr, cstr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -196,6 +202,7 @@
 		C.uint(flags),
 		handle,
 	)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -222,6 +229,7 @@
 		&cpathspecs,
 		handle,
 	)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -248,6 +256,7 @@
 		&cpathspecs,
 		handle,
 	)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -271,6 +280,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_index_remove_bypath(v.ptr, cstr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -287,6 +297,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_index_remove_directory(v.ptr, cstr, C.int(stage))
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -301,6 +312,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_index_write_tree_to(oid.toC(), v.ptr, repo.ptr)
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(repo)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -315,6 +328,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_index_read_tree(v.ptr, tree.cast_ptr)
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(tree)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -329,6 +344,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_index_write_tree(oid.toC(), v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -341,6 +357,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_index_write(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -354,7 +371,9 @@
 }
 
 func (v *Index) EntryCount() uint {
-	return uint(C.git_index_entrycount(v.ptr))
+	ret := uint(C.git_index_entrycount(v.ptr))
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) {
@@ -362,7 +381,9 @@
 	if centry == nil {
 		return nil, fmt.Errorf("Index out of Bounds")
 	}
-	return newIndexEntryFromC(centry), nil
+	ret := newIndexEntryFromC(centry)
+	runtime.KeepAlive(v)
+	return ret, nil
 }
 
 func (v *Index) EntryByPath(path string, stage int) (*IndexEntry, error) {
@@ -376,7 +397,9 @@
 	if centry == nil {
 		return nil, MakeGitError(C.GIT_ENOTFOUND)
 	}
-	return newIndexEntryFromC(centry), nil
+	ret := newIndexEntryFromC(centry)
+	runtime.KeepAlive(v)
+	return ret, nil
 }
 
 func (v *Index) Find(path string) (uint, error) {
@@ -388,6 +411,7 @@
 
 	var pos C.size_t
 	ret := C.git_index_find(&pos, v.ptr, cpath)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return uint(0), MakeGitError(ret)
 	}
@@ -403,6 +427,7 @@
 
 	var pos C.size_t
 	ret := C.git_index_find_prefix(&pos, v.ptr, cprefix)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return uint(0), MakeGitError(ret)
 	}
@@ -410,12 +435,15 @@
 }
 
 func (v *Index) HasConflicts() bool {
-	return C.git_index_has_conflicts(v.ptr) != 0
+	ret := C.git_index_has_conflicts(v.ptr) != 0
+	runtime.KeepAlive(v)
+	return ret
 }
 
 // FIXME: this might return an error
 func (v *Index) CleanupConflicts() {
 	C.git_index_conflict_cleanup(v.ptr)
+	runtime.KeepAlive(v)
 }
 
 func (v *Index) AddConflict(ancestor *IndexEntry, our *IndexEntry, their *IndexEntry) error {
@@ -446,6 +474,10 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_index_conflict_add(v.ptr, cancestor, cour, ctheir)
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(ancestor)
+	runtime.KeepAlive(our)
+	runtime.KeepAlive(their)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -474,11 +506,13 @@
 	if ecode < 0 {
 		return IndexConflict{}, MakeGitError(ecode)
 	}
-	return IndexConflict{
+	ret := IndexConflict{
 		Ancestor: newIndexEntryFromC(cancestor),
 		Our:      newIndexEntryFromC(cour),
 		Their:    newIndexEntryFromC(ctheir),
-	}, nil
+	}
+	runtime.KeepAlive(v)
+	return ret, nil
 }
 
 func (v *Index) RemoveConflict(path string) error {
@@ -490,6 +524,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_index_conflict_remove(v.ptr, cpath)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -541,9 +576,11 @@
 	if ecode < 0 {
 		return IndexConflict{}, MakeGitError(ecode)
 	}
-	return IndexConflict{
+	ret := IndexConflict{
 		Ancestor: newIndexEntryFromC(cancestor),
 		Our:      newIndexEntryFromC(cour),
 		Their:    newIndexEntryFromC(ctheir),
-	}, nil
+	}
+	runtime.KeepAlive(v)
+	return ret, nil
 }
diff --git a/merge.go b/merge.go
index b3fd818..bfbf9a3 100644
--- a/merge.go
+++ b/merge.go
@@ -18,10 +18,11 @@
 
 type AnnotatedCommit struct {
 	ptr *C.git_annotated_commit
+	r   *Repository
 }
 
-func newAnnotatedCommitFromC(c *C.git_annotated_commit) *AnnotatedCommit {
-	mh := &AnnotatedCommit{ptr: c}
+func newAnnotatedCommitFromC(ptr *C.git_annotated_commit, r *Repository) *AnnotatedCommit {
+	mh := &AnnotatedCommit{ptr: ptr, r: r}
 	runtime.SetFinalizer(mh, (*AnnotatedCommit).Free)
 	return mh
 }
@@ -32,8 +33,6 @@
 }
 
 func (r *Repository) AnnotatedCommitFromFetchHead(branchName string, remoteURL string, oid *Oid) (*AnnotatedCommit, error) {
-	mh := &AnnotatedCommit{}
-
 	cbranchName := C.CString(branchName)
 	defer C.free(unsafe.Pointer(cbranchName))
 
@@ -43,40 +42,41 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	ret := C.git_annotated_commit_from_fetchhead(&mh.ptr, r.ptr, cbranchName, cremoteURL, oid.toC())
+	var ptr *C.git_annotated_commit
+	ret := C.git_annotated_commit_from_fetchhead(&ptr, r.ptr, cbranchName, cremoteURL, oid.toC())
+	runtime.KeepAlive(oid)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
-	runtime.SetFinalizer(mh, (*AnnotatedCommit).Free)
-	return mh, nil
+
+	return newAnnotatedCommitFromC(ptr, r), nil
 }
 
 func (r *Repository) LookupAnnotatedCommit(oid *Oid) (*AnnotatedCommit, error) {
-	mh := &AnnotatedCommit{}
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	ret := C.git_annotated_commit_lookup(&mh.ptr, r.ptr, oid.toC())
+	var ptr *C.git_annotated_commit
+	ret := C.git_annotated_commit_lookup(&ptr, r.ptr, oid.toC())
+	runtime.KeepAlive(oid)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
-	runtime.SetFinalizer(mh, (*AnnotatedCommit).Free)
-	return mh, nil
+	return newAnnotatedCommitFromC(ptr, r), nil
 }
 
 func (r *Repository) AnnotatedCommitFromRef(ref *Reference) (*AnnotatedCommit, error) {
-	mh := &AnnotatedCommit{}
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	ret := C.git_annotated_commit_from_ref(&mh.ptr, r.ptr, ref.ptr)
+	var ptr *C.git_annotated_commit
+	ret := C.git_annotated_commit_from_ref(&ptr, r.ptr, ref.ptr)
+	runtime.KeepAlive(r)
+	runtime.KeepAlive(ref)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
-	runtime.SetFinalizer(mh, (*AnnotatedCommit).Free)
-	return mh, nil
+	return newAnnotatedCommitFromC(ptr, r), nil
 }
 
 type MergeTreeFlag int
@@ -162,6 +162,7 @@
 	}
 	ptr := unsafe.Pointer(&gmerge_head_array[0])
 	err := C.git_merge(r.ptr, (**C.git_annotated_commit)(ptr), C.size_t(len(theirHeads)), cMergeOpts, cCheckoutOpts)
+	runtime.KeepAlive(theirHeads)
 	if err < 0 {
 		return MakeGitError(err)
 	}
@@ -201,6 +202,7 @@
 	var analysis C.git_merge_analysis_t
 	var preference C.git_merge_preference_t
 	err := C.git_merge_analysis(&analysis, &preference, r.ptr, (**C.git_annotated_commit)(ptr), C.size_t(len(theirHeads)))
+	runtime.KeepAlive(theirHeads)
 	if err < 0 {
 		return MergeAnalysisNone, MergePreferenceNone, MakeGitError(err)
 	}
@@ -214,14 +216,15 @@
 
 	copts := options.toC()
 
-	idx := &Index{}
-
-	ret := C.git_merge_commits(&idx.ptr, r.ptr, ours.cast_ptr, theirs.cast_ptr, copts)
+	var ptr *C.git_index
+	ret := C.git_merge_commits(&ptr, r.ptr, ours.cast_ptr, theirs.cast_ptr, copts)
+	runtime.KeepAlive(ours)
+	runtime.KeepAlive(theirs)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
-	runtime.SetFinalizer(idx, (*Index).Free)
-	return idx, nil
+
+	return newIndexFromC(ptr, r), nil
 }
 
 func (r *Repository) MergeTrees(ancestor *Tree, ours *Tree, theirs *Tree, options *MergeOptions) (*Index, error) {
@@ -230,17 +233,20 @@
 
 	copts := options.toC()
 
-	idx := &Index{}
 	var ancestor_ptr *C.git_tree
 	if ancestor != nil {
 		ancestor_ptr = ancestor.cast_ptr
 	}
-	ret := C.git_merge_trees(&idx.ptr, r.ptr, ancestor_ptr, ours.cast_ptr, theirs.cast_ptr, copts)
+	var ptr *C.git_index
+	ret := C.git_merge_trees(&ptr, r.ptr, ancestor_ptr, ours.cast_ptr, theirs.cast_ptr, copts)
+	runtime.KeepAlive(ancestor)
+	runtime.KeepAlive(ours)
+	runtime.KeepAlive(theirs)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
-	runtime.SetFinalizer(idx, (*Index).Free)
-	return idx, nil
+
+	return newIndexFromC(ptr, r), nil
 }
 
 func (r *Repository) MergeBase(one *Oid, two *Oid) (*Oid, error) {
@@ -249,6 +255,9 @@
 
 	var oid C.git_oid
 	ret := C.git_merge_base(&oid, r.ptr, one.toC(), two.toC())
+	runtime.KeepAlive(one)
+	runtime.KeepAlive(two)
+	runtime.KeepAlive(r)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -265,6 +274,8 @@
 
 	var coids C.git_oidarray
 	ret := C.git_merge_bases(&coids, r.ptr, one.toC(), two.toC())
+	runtime.KeepAlive(one)
+	runtime.KeepAlive(two)
 	if ret < 0 {
 		return make([]*Oid, 0), MakeGitError(ret)
 	}
@@ -413,6 +424,9 @@
 		(*C.char)(unsafe.Pointer(oursContents)), C.size_t(len(ours.Contents)), oursPath, C.uint(ours.Mode),
 		(*C.char)(unsafe.Pointer(theirsContents)), C.size_t(len(theirs.Contents)), theirsPath, C.uint(theirs.Mode),
 		copts)
+	runtime.KeepAlive(ancestor)
+	runtime.KeepAlive(ours)
+	runtime.KeepAlive(theirs)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
diff --git a/note.go b/note.go
index a1b15d8..21bed57 100644
--- a/note.go
+++ b/note.go
@@ -52,7 +52,8 @@
 	ret := C.git_note_create(
 		oid.toC(), c.repo.ptr, cref, authorSig,
 		committerSig, id.toC(), cnote, cbool(force))
-
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(id)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -69,17 +70,18 @@
 		defer C.free(unsafe.Pointer(cref))
 	}
 
-	note := new(Note)
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_note_read(&note.ptr, c.repo.ptr, cref, id.toC()); ret < 0 {
+	var ptr *C.git_note
+	ret := C.git_note_read(&ptr, c.repo.ptr, cref, id.toC())
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(id)
+	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
 
-	runtime.SetFinalizer(note, (*Note).Free)
-	return note, nil
+	return newNoteFromC(ptr, c.repo), nil
 }
 
 // Remove removes the note for an object
@@ -108,6 +110,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_note_remove(c.repo.ptr, cref, authorSig, committerSig, id.toC())
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(id)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -121,8 +125,10 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_note_default_ref(&buf, c.repo.ptr); ret < 0 {
-		return "", MakeGitError(ret)
+	ecode := C.git_note_default_ref(&buf, c.repo.ptr)
+	runtime.KeepAlive(c)
+	if ecode < 0 {
+		return "", MakeGitError(ecode)
 	}
 
 	ret := C.GoString(buf.ptr)
@@ -134,6 +140,13 @@
 // Note
 type Note struct {
 	ptr *C.git_note
+	r   *Repository
+}
+
+func newNoteFromC(ptr *C.git_note, r *Repository) *Note {
+	note := &Note{ptr: ptr, r: r}
+	runtime.SetFinalizer(note, (*Note).Free)
+	return note
 }
 
 // Free frees a git_note object
@@ -156,23 +169,28 @@
 // Id returns the note object's id
 func (n *Note) Id() *Oid {
 	ptr := C.git_note_id(n.ptr)
+	runtime.KeepAlive(n)
 	return newOidFromC(ptr)
 }
 
 // Committer returns the signature of the note committer
 func (n *Note) Committer() *Signature {
 	ptr := C.git_note_committer(n.ptr)
+	runtime.KeepAlive(n)
 	return newSignatureFromC(ptr)
 }
 
 // Message returns the note message
 func (n *Note) Message() string {
-	return C.GoString(C.git_note_message(n.ptr))
+	ret := C.GoString(C.git_note_message(n.ptr))
+	runtime.KeepAlive(n)
+	return ret
 }
 
 // NoteIterator
 type NoteIterator struct {
 	ptr *C.git_note_iterator
+	r   *Repository
 }
 
 // NewNoteIterator creates a new iterator for notes
@@ -190,11 +208,13 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_note_iterator_new(&ptr, repo.ptr, cref); ret < 0 {
+	ret := C.git_note_iterator_new(&ptr, repo.ptr, cref)
+	runtime.KeepAlive(repo)
+	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
 
-	iter := &NoteIterator{ptr: ptr}
+	iter := &NoteIterator{ptr: ptr, r: repo}
 	runtime.SetFinalizer(iter, (*NoteIterator).Free)
 	return iter, nil
 }
@@ -213,7 +233,11 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_note_next(noteId.toC(), annotatedId.toC(), it.ptr); ret < 0 {
+	ret := C.git_note_next(noteId.toC(), annotatedId.toC(), it.ptr)
+	runtime.KeepAlive(noteId)
+	runtime.KeepAlive(annotatedId)
+	runtime.KeepAlive(it)
+	if ret < 0 {
 		err = MakeGitError(ret)
 	}
 	return
diff --git a/object.go b/object.go
index b365a3f..f4f1b3e 100644
--- a/object.go
+++ b/object.go
@@ -46,7 +46,9 @@
 }
 
 func (o *Object) Id() *Oid {
-	return newOidFromC(C.git_object_id(o.ptr))
+	ret := newOidFromC(C.git_object_id(o.ptr))
+	runtime.KeepAlive(o)
+	return ret
 }
 
 func (o *Object) ShortId() (string, error) {
@@ -56,6 +58,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_object_short_id(&resultBuf, o.ptr)
+	runtime.KeepAlive(o)
 	if ecode < 0 {
 		return "", MakeGitError(ecode)
 	}
@@ -64,15 +67,19 @@
 }
 
 func (o *Object) Type() ObjectType {
-	return ObjectType(C.git_object_type(o.ptr))
+	ret := ObjectType(C.git_object_type(o.ptr))
+	runtime.KeepAlive(o)
+	return ret
 }
 
 // Owner returns a weak reference to the repository which owns this
 // object. This won't keep the underlying repository alive.
 func (o *Object) Owner() *Repository {
-	return &Repository{
+	ret := &Repository{
 		ptr: C.git_object_owner(o.ptr),
 	}
+	runtime.KeepAlive(o)
+	return ret
 }
 
 func dupObject(obj *Object, kind ObjectType) (*C.git_object, error) {
@@ -85,7 +92,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if err := C.git_object_dup(&cobj, obj.ptr); err < 0 {
+	err := C.git_object_dup(&cobj, obj.ptr)
+	runtime.KeepAlive(obj)
+	if err < 0 {
 		return nil, MakeGitError(err)
 	}
 
@@ -203,7 +212,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if err := C.git_object_peel(&cobj, o.ptr, C.git_otype(t)); err < 0 {
+	err := C.git_object_peel(&cobj, o.ptr, C.git_otype(t))
+	runtime.KeepAlive(o)
+	if err < 0 {
 		return nil, MakeGitError(err)
 	}
 
diff --git a/odb.go b/odb.go
index a728cd3..64c5415 100644
--- a/odb.go
+++ b/odb.go
@@ -47,6 +47,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_add_backend(v.ptr, backend.ptr, C.int(priority))
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		backend.Free()
 		return MakeGitError(ret)
@@ -57,20 +58,23 @@
 func (v *Odb) ReadHeader(oid *Oid) (uint64, ObjectType, error) {
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
-	
+
 	var sz C.size_t
-	var cotype C.git_otype 
+	var cotype C.git_otype
 
 	ret := C.git_odb_read_header(&sz, &cotype, v.ptr, oid.toC())
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return 0, C.GIT_OBJ_BAD, MakeGitError(ret)
 	}
 
 	return uint64(sz), ObjectType(cotype), nil
 }
-	
+
 func (v *Odb) Exists(oid *Oid) bool {
 	ret := C.git_odb_exists(v.ptr, oid.toC())
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(oid)
 	return ret != 0
 }
 
@@ -85,7 +89,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_write(oid.toC(), v.ptr, cptr, C.size_t(len(data)), C.git_otype(otype))
-
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -100,6 +104,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_read(&obj.ptr, v.ptr, oid.toC())
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(oid)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -145,6 +151,7 @@
 	defer pointerHandles.Untrack(handle)
 
 	ret := C._go_git_odb_foreach(v.ptr, handle)
+	runtime.KeepAlive(v)
 	if ret == C.GIT_EUSER {
 		return data.err
 	} else if ret < 0 {
@@ -164,6 +171,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_hash(oid.toC(), ptr, C.size_t(header.Len), C.git_otype(otype))
+	runtime.KeepAlive(data)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -179,6 +187,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_open_rstream(&stream.ptr, v.ptr, id.toC())
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(id)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -197,6 +207,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.git_off_t(size), C.git_otype(otype))
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -219,17 +230,25 @@
 }
 
 func (object *OdbObject) Id() (oid *Oid) {
-	return newOidFromC(C.git_odb_object_id(object.ptr))
+	ret := newOidFromC(C.git_odb_object_id(object.ptr))
+	runtime.KeepAlive(object)
+	return ret
 }
 
 func (object *OdbObject) Len() (len uint64) {
-	return uint64(C.git_odb_object_size(object.ptr))
+	ret := uint64(C.git_odb_object_size(object.ptr))
+	runtime.KeepAlive(object)
+	return ret
 }
 
 func (object *OdbObject) Type() ObjectType {
-	return ObjectType(C.git_odb_object_type(object.ptr))
+	ret := ObjectType(C.git_odb_object_type(object.ptr))
+	runtime.KeepAlive(object)
+	return ret
 }
 
+// Data returns a slice pointing to the unmanaged object memory. You must make
+// sure the object is referenced for at least as long as the slice is used.
 func (object *OdbObject) Data() (data []byte) {
 	var c_blob unsafe.Pointer = C.git_odb_object_data(object.ptr)
 	var blob []byte
@@ -258,6 +277,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_stream_read(stream.ptr, ptr, size)
+	runtime.KeepAlive(stream)
 	if ret < 0 {
 		return 0, MakeGitError(ret)
 	}
@@ -293,6 +313,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_stream_write(stream.ptr, ptr, size)
+	runtime.KeepAlive(stream)
 	if ret < 0 {
 		return 0, MakeGitError(ret)
 	}
@@ -307,6 +328,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_odb_stream_finalize_write(stream.Id.toC(), stream.ptr)
+	runtime.KeepAlive(stream)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
diff --git a/packbuilder.go b/packbuilder.go
index 4dc352c..0e04bbf 100644
--- a/packbuilder.go
+++ b/packbuilder.go
@@ -17,20 +17,25 @@
 
 type Packbuilder struct {
 	ptr *C.git_packbuilder
+	r   *Repository
 }
 
 func (repo *Repository) NewPackbuilder() (*Packbuilder, error) {
-	builder := &Packbuilder{}
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	ret := C.git_packbuilder_new(&builder.ptr, repo.ptr)
+	var ptr *C.git_packbuilder
+	ret := C.git_packbuilder_new(&ptr, repo.ptr)
 	if ret != 0 {
 		return nil, MakeGitError(ret)
 	}
-	runtime.SetFinalizer(builder, (*Packbuilder).Free)
-	return builder, nil
+	return newPackbuilderFromC(ptr, repo), nil
+}
+
+func newPackbuilderFromC(ptr *C.git_packbuilder, r *Repository) *Packbuilder {
+	pb := &Packbuilder{ptr: ptr, r: r}
+	runtime.SetFinalizer(pb, (*Packbuilder).Free)
+	return pb
 }
 
 func (pb *Packbuilder) Free() {
@@ -46,6 +51,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_packbuilder_insert(pb.ptr, id.toC(), cname)
+	runtime.KeepAlive(pb)
+	runtime.KeepAlive(id)
 	if ret != 0 {
 		return MakeGitError(ret)
 	}
@@ -57,6 +64,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_packbuilder_insert_commit(pb.ptr, id.toC())
+	runtime.KeepAlive(pb)
+	runtime.KeepAlive(id)
 	if ret != 0 {
 		return MakeGitError(ret)
 	}
@@ -68,6 +77,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_packbuilder_insert_tree(pb.ptr, id.toC())
+	runtime.KeepAlive(pb)
+	runtime.KeepAlive(id)
 	if ret != 0 {
 		return MakeGitError(ret)
 	}
@@ -75,7 +86,9 @@
 }
 
 func (pb *Packbuilder) ObjectCount() uint32 {
-	return uint32(C.git_packbuilder_object_count(pb.ptr))
+	ret := uint32(C.git_packbuilder_object_count(pb.ptr))
+	runtime.KeepAlive(pb)
+	return ret
 }
 
 func (pb *Packbuilder) WriteToFile(name string, mode os.FileMode) error {
@@ -86,6 +99,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_packbuilder_write(pb.ptr, cname, C.uint(mode.Perm()), nil, nil)
+	runtime.KeepAlive(pb)
 	if ret != 0 {
 		return MakeGitError(ret)
 	}
@@ -100,7 +114,9 @@
 }
 
 func (pb *Packbuilder) Written() uint32 {
-	return uint32(C.git_packbuilder_written(pb.ptr))
+	ret := uint32(C.git_packbuilder_written(pb.ptr))
+	runtime.KeepAlive(pb)
+	return ret
 }
 
 type PackbuilderForeachCallback func([]byte) error
@@ -142,6 +158,7 @@
 	defer runtime.UnlockOSThread()
 
 	err := C._go_git_packbuilder_foreach(pb.ptr, handle)
+	runtime.KeepAlive(pb)
 	if err == C.GIT_EUSER {
 		return data.err
 	}
diff --git a/patch.go b/patch.go
index 0d0df7f..75e843c 100644
--- a/patch.go
+++ b/patch.go
@@ -47,6 +47,7 @@
 	var buf C.git_buf
 
 	ecode := C.git_patch_to_buf(&buf, patch.ptr)
+	runtime.KeepAlive(patch)
 	if ecode < 0 {
 		return "", MakeGitError(ecode)
 	}
@@ -83,6 +84,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_patch_from_buffers(&patchPtr, oldPtr, C.size_t(len(oldBuf)), cOldPath, newPtr, C.size_t(len(newBuf)), cNewPath, copts)
+	runtime.KeepAlive(oldBuf)
+	runtime.KeepAlive(newBuf)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
diff --git a/rebase.go b/rebase.go
index 8553e25..390b924 100644
--- a/rebase.go
+++ b/rebase.go
@@ -100,6 +100,7 @@
 // Rebase is the struct representing a Rebase object.
 type Rebase struct {
 	ptr *C.git_rebase
+	r   *Repository
 }
 
 // InitRebase initializes a rebase operation to rebase the changes in branch relative to upstream onto another branch.
@@ -121,6 +122,9 @@
 
 	var ptr *C.git_rebase
 	err := C.git_rebase_init(&ptr, r.ptr, branch.ptr, upstream.ptr, onto.ptr, opts.toC())
+	runtime.KeepAlive(branch)
+	runtime.KeepAlive(upstream)
+	runtime.KeepAlive(onto)
 	if err < 0 {
 		return nil, MakeGitError(err)
 	}
@@ -135,6 +139,7 @@
 
 	var ptr *C.git_rebase
 	err := C.git_rebase_open(&ptr, r.ptr, opts.toC())
+	runtime.KeepAlive(r)
 	if err < 0 {
 		return nil, MakeGitError(err)
 	}
@@ -145,7 +150,7 @@
 // OperationAt gets the rebase operation specified by the given index.
 func (rebase *Rebase) OperationAt(index uint) *RebaseOperation {
 	operation := C.git_rebase_operation_byindex(rebase.ptr, C.size_t(index))
-	
+
 	return newRebaseOperationFromC(operation)
 }
 
@@ -165,7 +170,9 @@
 
 // OperationCount gets the count of rebase operations that are to be applied.
 func (rebase *Rebase) OperationCount() uint {
-	return uint(C.git_rebase_operation_entrycount(rebase.ptr))
+	ret := uint(C.git_rebase_operation_entrycount(rebase.ptr))
+	runtime.KeepAlive(rebase)
+	return ret
 }
 
 // Next performs the next rebase operation and returns the information about it.
@@ -178,6 +185,7 @@
 
 	var ptr *C.git_rebase_operation
 	err := C.git_rebase_next(&ptr, rebase.ptr)
+	runtime.KeepAlive(rebase)
 	if err < 0 {
 		return nil, MakeGitError(err)
 	}
@@ -207,6 +215,8 @@
 	defer C.free(unsafe.Pointer(cmsg))
 
 	cerr := C.git_rebase_commit(ID.toC(), rebase.ptr, authorSig, committerSig, nil, cmsg)
+	runtime.KeepAlive(ID)
+	runtime.KeepAlive(rebase)
 	if cerr < 0 {
 		return MakeGitError(cerr)
 	}
@@ -220,6 +230,7 @@
 	defer runtime.UnlockOSThread()
 
 	err := C.git_rebase_finish(rebase.ptr, nil)
+	runtime.KeepAlive(rebase)
 	if err < 0 {
 		return MakeGitError(err)
 	}
@@ -233,6 +244,7 @@
 	defer runtime.UnlockOSThread()
 
 	err := C.git_rebase_abort(rebase.ptr)
+	runtime.KeepAlive(rebase)
 	if err < 0 {
 		return MakeGitError(err)
 	}
diff --git a/refdb.go b/refdb.go
index 4e3ebf9..578f43c 100644
--- a/refdb.go
+++ b/refdb.go
@@ -14,6 +14,7 @@
 
 type Refdb struct {
 	ptr *C.git_refdb
+	r   *Repository
 }
 
 type RefdbBackend struct {
@@ -21,16 +22,17 @@
 }
 
 func (v *Repository) NewRefdb() (refdb *Refdb, err error) {
-	refdb = new(Refdb)
+	var ptr *C.git_refdb
 
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	ret := C.git_refdb_new(&refdb.ptr, v.ptr)
+	ret := C.git_refdb_new(&ptr, v.ptr)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
 
+	refdb = &Refdb{ptr: ptr, r: v}
 	runtime.SetFinalizer(refdb, (*Refdb).Free)
 	return refdb, nil
 }
@@ -45,6 +47,8 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_refdb_set_backend(v.ptr, backend.ptr)
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(backend)
 	if ret < 0 {
 		backend.Free()
 		return MakeGitError(ret)
@@ -53,5 +57,6 @@
 }
 
 func (v *RefdbBackend) Free() {
+	runtime.SetFinalizer(v, nil)
 	C._go_git_refdb_backend_free(v.ptr)
 }
diff --git a/reference.go b/reference.go
index 463f2fc..e10c9b2 100644
--- a/reference.go
+++ b/reference.go
@@ -34,6 +34,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_reference_lookup(&ptr, c.repo.ptr, cname)
+	runtime.KeepAlive(c)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -59,6 +60,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_reference_create(&ptr, c.repo.ptr, cname, id.toC(), cbool(force), cmsg)
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(id)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -87,6 +90,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_reference_symbolic_create(&ptr, c.repo.ptr, cname, ctarget, cbool(force), cmsg)
+	runtime.KeepAlive(c)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -104,6 +108,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_reference_ensure_log(c.repo.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -121,6 +126,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_reference_has_log(c.repo.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -138,6 +144,7 @@
 
 	var ptr *C.git_reference
 	ret := C.git_reference_dwim(&ptr, c.repo.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -169,6 +176,7 @@
 	}
 
 	ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget, cmsg)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -191,6 +199,7 @@
 	}
 
 	ret := C.git_reference_set_target(&ptr, v.ptr, target.toC(), cmsg)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -205,6 +214,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_reference_resolve(&ptr, v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -229,7 +239,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_reference_rename(&ptr, v.ptr, cname, cbool(force), cmsg)
-
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -238,16 +248,21 @@
 }
 
 func (v *Reference) Target() *Oid {
-	return newOidFromC(C.git_reference_target(v.ptr))
+	ret := newOidFromC(C.git_reference_target(v.ptr))
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Reference) SymbolicTarget() string {
+	var ret string
 	cstr := C.git_reference_symbolic_target(v.ptr)
-	if cstr == nil {
-		return ""
+
+	if cstr != nil {
+		return C.GoString(cstr)
 	}
 
-	return C.GoString(cstr)
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Reference) Delete() error {
@@ -255,7 +270,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_reference_delete(v.ptr)
-
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -269,7 +284,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if err := C.git_reference_peel(&cobj, v.ptr, C.git_otype(t)); err < 0 {
+	err := C.git_reference_peel(&cobj, v.ptr, C.git_otype(t))
+	runtime.KeepAlive(v)
+	if err < 0 {
 		return nil, MakeGitError(err)
 	}
 
@@ -287,37 +304,54 @@
 // Cmp compares both references, retursn 0 on equality, otherwise a
 // stable sorting.
 func (v *Reference) Cmp(ref2 *Reference) int {
-	return int(C.git_reference_cmp(v.ptr, ref2.ptr))
+	ret := int(C.git_reference_cmp(v.ptr, ref2.ptr))
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(ref2)
+	return ret
 }
 
-// Shorthand returns a "human-readable" short reference name
+// Shorthand ret :=s a "human-readable" short reference name
 func (v *Reference) Shorthand() string {
-	return C.GoString(C.git_reference_shorthand(v.ptr))
+	ret := C.GoString(C.git_reference_shorthand(v.ptr))
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Reference) Name() string {
-	return C.GoString(C.git_reference_name(v.ptr))
+	ret := C.GoString(C.git_reference_name(v.ptr))
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Reference) Type() ReferenceType {
-	return ReferenceType(C.git_reference_type(v.ptr))
+	ret := ReferenceType(C.git_reference_type(v.ptr))
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Reference) IsBranch() bool {
-	return C.git_reference_is_branch(v.ptr) == 1
+	ret := C.git_reference_is_branch(v.ptr) == 1
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Reference) IsRemote() bool {
-	return C.git_reference_is_remote(v.ptr) == 1
+	ret := C.git_reference_is_remote(v.ptr) == 1
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Reference) IsTag() bool {
-	return C.git_reference_is_tag(v.ptr) == 1
+	ret := C.git_reference_is_tag(v.ptr) == 1
+	runtime.KeepAlive(v)
+	return ret
 }
 
 // IsNote checks if the reference is a note.
 func (v *Reference) IsNote() bool {
-	return C.git_reference_is_note(v.ptr) == 1
+	ret := C.git_reference_is_note(v.ptr) == 1
+	runtime.KeepAlive(v)
+	return ret
 }
 
 func (v *Reference) Free() {
@@ -346,9 +380,7 @@
 		return nil, MakeGitError(ret)
 	}
 
-	iter := &ReferenceIterator{ptr: ptr, repo: repo}
-	runtime.SetFinalizer(iter, (*ReferenceIterator).Free)
-	return iter, nil
+	return newReferenceIteratorFromC(ptr, repo), nil
 }
 
 // NewReferenceIterator creates a new branch iterator over reference names
@@ -363,8 +395,7 @@
 		return nil, MakeGitError(ret)
 	}
 
-	iter := &ReferenceIterator{ptr: ptr, repo: repo}
-	runtime.SetFinalizer(iter, (*ReferenceIterator).Free)
+	iter := newReferenceIteratorFromC(ptr, repo)
 	return iter.Names(), nil
 }
 
@@ -384,9 +415,7 @@
 		return nil, MakeGitError(ret)
 	}
 
-	iter := &ReferenceIterator{ptr: ptr}
-	runtime.SetFinalizer(iter, (*ReferenceIterator).Free)
-	return iter, nil
+	return newReferenceIteratorFromC(ptr, repo), nil
 }
 
 func (i *ReferenceIterator) Names() *ReferenceNameIterator {
@@ -425,6 +454,13 @@
 	return newReferenceFromC(ptr, v.repo), nil
 }
 
+func newReferenceIteratorFromC(ptr *C.git_reference_iterator, r *Repository) *ReferenceIterator {
+	return &ReferenceIterator{
+		ptr:  ptr,
+		repo: r,
+	}
+}
+
 // Free the reference iterator
 func (v *ReferenceIterator) Free() {
 	runtime.SetFinalizer(v, nil)
diff --git a/repository.go b/repository.go
index a44b9b8..abf8b71 100644
--- a/repository.go
+++ b/repository.go
@@ -120,6 +120,7 @@
 
 	var ptr *C.git_repository
 	ret := C.git_repository_wrap_odb(&ptr, odb.ptr)
+	runtime.KeepAlive(odb)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -129,6 +130,7 @@
 
 func (v *Repository) SetRefdb(refdb *Refdb) {
 	C.git_repository_set_refdb(v.ptr, refdb.ptr)
+	runtime.KeepAlive(v)
 }
 
 func (v *Repository) Free() {
@@ -143,6 +145,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_config(&config.ptr, v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -162,7 +165,7 @@
 		return nil, MakeGitError(ret)
 	}
 
-	return newIndexFromC(ptr), nil
+	return newIndexFromC(ptr, v), nil
 }
 
 func (v *Repository) lookupType(id *Oid, t ObjectType) (*Object, error) {
@@ -172,6 +175,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_object_lookup(&ptr, v.ptr, id.toC(), C.git_otype(t))
+	runtime.KeepAlive(id)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -241,6 +245,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_repository_set_head(v.ptr, cname)
+	runtime.KeepAlive(v)
 	if ecode != 0 {
 		return MakeGitError(ecode)
 	}
@@ -252,6 +257,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_repository_set_head_detached(v.ptr, id.toC())
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(id)
 	if ecode != 0 {
 		return MakeGitError(ecode)
 	}
@@ -263,6 +270,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_head_detached(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -275,6 +283,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_head_unborn(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -286,6 +295,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_is_empty(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -298,6 +308,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_is_shallow(v.ptr)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return false, MakeGitError(ret)
 	}
@@ -368,6 +379,9 @@
 		authorSig, committerSig,
 		nil, cmsg, tree.cast_ptr, C.size_t(nparents), parentsarg)
 
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(oid)
+	runtime.KeepAlive(parents)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -391,7 +405,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_repository_odb(&odb.ptr, v.ptr); ret < 0 {
+	ret := C.git_repository_odb(&odb.ptr, v.ptr)
+	runtime.KeepAlive(v)
+	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
 
@@ -400,15 +416,21 @@
 }
 
 func (repo *Repository) Path() string {
-	return C.GoString(C.git_repository_path(repo.ptr))
+	s := C.GoString(C.git_repository_path(repo.ptr))
+	runtime.KeepAlive(repo)
+	return s
 }
 
 func (repo *Repository) IsBare() bool {
-	return C.git_repository_is_bare(repo.ptr) != 0
+	ret := C.git_repository_is_bare(repo.ptr) != 0
+	runtime.KeepAlive(repo)
+	return ret
 }
 
 func (repo *Repository) Workdir() string {
-	return C.GoString(C.git_repository_workdir(repo.ptr))
+	s := C.GoString(C.git_repository_workdir(repo.ptr))
+	runtime.KeepAlive(repo)
+	return s
 }
 
 func (repo *Repository) SetWorkdir(workdir string, updateGitlink bool) error {
@@ -421,6 +443,7 @@
 	if ret := C.git_repository_set_workdir(repo.ptr, cstr, cbool(updateGitlink)); ret < 0 {
 		return MakeGitError(ret)
 	}
+	runtime.KeepAlive(repo)
 
 	return nil
 }
@@ -434,6 +457,7 @@
 	if ret := C.git_treebuilder_new(&bld.ptr, v.ptr, nil); ret < 0 {
 		return nil, MakeGitError(ret)
 	}
+
 	runtime.SetFinalizer(bld, (*TreeBuilder).Free)
 
 	bld.repo = v
@@ -474,7 +498,10 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	return RepositoryState(C.git_repository_state(r.ptr))
+	ret := RepositoryState(C.git_repository_state(r.ptr))
+	runtime.KeepAlive(r)
+
+	return ret
 }
 
 func (r *Repository) StateCleanup() error {
@@ -482,18 +509,22 @@
 	defer runtime.UnlockOSThread()
 
 	cErr := C.git_repository_state_cleanup(r.ptr)
+	runtime.KeepAlive(r)
 	if cErr < 0 {
 		return MakeGitError(cErr)
 	}
 	return nil
 }
+
 func (r *Repository) AddGitIgnoreRules(rules string) error {
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
 	crules := C.CString(rules)
 	defer C.free(unsafe.Pointer(crules))
-	if ret := C.git_ignore_add_rule(r.ptr, crules); ret < 0 {
+	ret := C.git_ignore_add_rule(r.ptr, crules)
+	runtime.KeepAlive(r)
+	if ret < 0 {
 		return MakeGitError(ret)
 	}
 	return nil
@@ -503,7 +534,9 @@
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_ignore_clear_internal_rules(r.ptr); ret < 0 {
+	ret := C.git_ignore_clear_internal_rules(r.ptr)
+	runtime.KeepAlive(r)
+	if ret < 0 {
 		return MakeGitError(ret)
 	}
 	return nil
diff --git a/signature.go b/signature.go
index 0518387..16964d2 100644
--- a/signature.go
+++ b/signature.go
@@ -63,6 +63,7 @@
 	defer runtime.UnlockOSThread()
 
 	cErr := C.git_signature_default(&out, repo.ptr)
+	runtime.KeepAlive(repo)
 	if cErr < 0 {
 		return nil, MakeGitError(cErr)
 	}
diff --git a/stash.go b/stash.go
index 809732e..8743da8 100644
--- a/stash.go
+++ b/stash.go
@@ -63,7 +63,7 @@
 	ret := C.git_stash_save(
 		oid.toC(), c.repo.ptr,
 		stasherC, messageC, C.uint32_t(flags))
-
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -228,6 +228,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_stash_apply(c.repo.ptr, C.size_t(index), optsC)
+	runtime.KeepAlive(c)
 	if ret == C.GIT_EUSER {
 		return progressData.Error
 	}
@@ -282,6 +283,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C._go_git_stash_foreach(c.repo.ptr, handle)
+	runtime.KeepAlive(c)
 	if ret == C.GIT_EUSER {
 		return data.Error
 	}
@@ -303,6 +305,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_stash_drop(c.repo.ptr, C.size_t(index))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -328,6 +331,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_stash_pop(c.repo.ptr, C.size_t(index), optsC)
+	runtime.KeepAlive(c)
 	if ret == C.GIT_EUSER {
 		return progressData.Error
 	}
diff --git a/status.go b/status.go
index e68e6e9..e37a96d 100644
--- a/status.go
+++ b/status.go
@@ -55,15 +55,17 @@
 
 type StatusList struct {
 	ptr *C.git_status_list
+	r   *Repository
 }
 
-func newStatusListFromC(ptr *C.git_status_list) *StatusList {
+func newStatusListFromC(ptr *C.git_status_list, r *Repository) *StatusList {
 	if ptr == nil {
 		return nil
 	}
 
 	statusList := &StatusList{
 		ptr: ptr,
+		r:   r,
 	}
 
 	runtime.SetFinalizer(statusList, (*StatusList).Free)
@@ -84,14 +86,20 @@
 		return StatusEntry{}, ErrInvalid
 	}
 	ptr := C.git_status_byindex(statusList.ptr, C.size_t(index))
-	return statusEntryFromC(ptr), nil
+	entry := statusEntryFromC(ptr)
+	runtime.KeepAlive(statusList)
+
+	return entry, nil
 }
 
 func (statusList *StatusList) EntryCount() (int, error) {
 	if statusList.ptr == nil {
 		return -1, ErrInvalid
 	}
-	return int(C.git_status_list_entrycount(statusList.ptr)), nil
+	ret := int(C.git_status_list_entrycount(statusList.ptr))
+	runtime.KeepAlive(statusList)
+
+	return ret, nil
 }
 
 type StatusOpt int
@@ -161,7 +169,7 @@
 		return nil, MakeGitError(ret)
 	}
 
-	return newStatusListFromC(ptr), nil
+	return newStatusListFromC(ptr, v), nil
 }
 
 func (v *Repository) StatusFile(path string) (Status, error) {
@@ -173,6 +181,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_status_file(&statusFlags, v.ptr, cPath)
+	runtime.KeepAlive(v)
 	if ret < 0 {
 		return 0, MakeGitError(ret)
 	}
diff --git a/submodule.go b/submodule.go
index 4a32ce4..406ed08 100644
--- a/submodule.go
+++ b/submodule.go
@@ -21,6 +21,18 @@
 // Submodule
 type Submodule struct {
 	ptr *C.git_submodule
+	r   *Repository
+}
+
+func newSubmoduleFromC(ptr *C.git_submodule, r *Repository) *Submodule {
+	s := &Submodule{ptr: ptr, r: r}
+	runtime.SetFinalizer(s, (*Submodule).Free)
+	return s
+}
+
+func (sub *Submodule) Free() {
+	runtime.SetFinalizer(sub, nil)
+	C.git_submodule_free(sub.ptr)
 }
 
 type SubmoduleUpdate int
@@ -82,24 +94,24 @@
 	cname := C.CString(name)
 	defer C.free(unsafe.Pointer(cname))
 
-	sub := new(Submodule)
+	var ptr *C.git_submodule
 
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	ret := C.git_submodule_lookup(&sub.ptr, c.repo.ptr, cname)
+	ret := C.git_submodule_lookup(&ptr, c.repo.ptr, cname)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
 
-	return sub, nil
+	return newSubmoduleFromC(ptr, c.repo), nil
 }
 
 type SubmoduleCbk func(sub *Submodule, name string) int
 
 //export SubmoduleVisitor
 func SubmoduleVisitor(csub unsafe.Pointer, name *C.char, handle unsafe.Pointer) C.int {
-	sub := &Submodule{(*C.git_submodule)(csub)}
+	sub := &Submodule{(*C.git_submodule)(csub), nil}
 
 	if callback, ok := pointerHandles.Get(handle).(SubmoduleCbk); ok {
 		return (C.int)(callback(sub, C.GoString(name)))
@@ -116,6 +128,7 @@
 	defer pointerHandles.Untrack(handle)
 
 	ret := C._go_git_visit_submodule(c.repo.ptr, handle)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -128,16 +141,15 @@
 	cpath := C.CString(path)
 	defer C.free(unsafe.Pointer(cpath))
 
-	sub := new(Submodule)
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	ret := C.git_submodule_add_setup(&sub.ptr, c.repo.ptr, curl, cpath, cbool(use_git_link))
+	var ptr *C.git_submodule
+	ret := C.git_submodule_add_setup(&ptr, c.repo.ptr, curl, cpath, cbool(use_git_link))
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
-	return sub, nil
+	return newSubmoduleFromC(ptr, c.repo), nil
 }
 
 func (sub *Submodule) FinalizeAdd() error {
@@ -145,6 +157,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_add_finalize(sub.ptr)
+	runtime.KeepAlive(sub)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -156,6 +169,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_add_to_index(sub.ptr, cbool(write_index))
+	runtime.KeepAlive(sub)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -163,18 +177,21 @@
 }
 
 func (sub *Submodule) Name() string {
-	n := C.git_submodule_name(sub.ptr)
-	return C.GoString(n)
+	n := C.GoString(C.git_submodule_name(sub.ptr))
+	runtime.KeepAlive(sub)
+	return n
 }
 
 func (sub *Submodule) Path() string {
-	n := C.git_submodule_path(sub.ptr)
-	return C.GoString(n)
+	n := C.GoString(C.git_submodule_path(sub.ptr))
+	runtime.KeepAlive(sub)
+	return n
 }
 
 func (sub *Submodule) Url() string {
-	n := C.git_submodule_url(sub.ptr)
-	return C.GoString(n)
+	n := C.GoString(C.git_submodule_url(sub.ptr))
+	runtime.KeepAlive(sub)
+	return n
 }
 
 func (c *SubmoduleCollection) SetUrl(submodule, url string) error {
@@ -187,6 +204,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_set_url(c.repo.ptr, csubmodule, curl)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -194,31 +212,38 @@
 }
 
 func (sub *Submodule) IndexId() *Oid {
+	var id *Oid
 	idx := C.git_submodule_index_id(sub.ptr)
-	if idx == nil {
-		return nil
+	if idx != nil {
+		id = newOidFromC(idx)
 	}
-	return newOidFromC(idx)
+	runtime.KeepAlive(sub)
+	return id
 }
 
 func (sub *Submodule) HeadId() *Oid {
+	var id *Oid
 	idx := C.git_submodule_head_id(sub.ptr)
-	if idx == nil {
-		return nil
+	if idx != nil {
+		id = newOidFromC(idx)
 	}
-	return newOidFromC(idx)
+	runtime.KeepAlive(sub)
+	return id
 }
 
 func (sub *Submodule) WdId() *Oid {
+	var id *Oid
 	idx := C.git_submodule_wd_id(sub.ptr)
-	if idx == nil {
-		return nil
+	if idx != nil {
+		id = newOidFromC(idx)
 	}
-	return newOidFromC(idx)
+	runtime.KeepAlive(sub)
+	return id
 }
 
 func (sub *Submodule) Ignore() SubmoduleIgnore {
 	o := C.git_submodule_ignore(sub.ptr)
+	runtime.KeepAlive(sub)
 	return SubmoduleIgnore(o)
 }
 
@@ -230,6 +255,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_set_ignore(c.repo.ptr, csubmodule, C.git_submodule_ignore_t(ignore))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -239,6 +265,7 @@
 
 func (sub *Submodule) UpdateStrategy() SubmoduleUpdate {
 	o := C.git_submodule_update_strategy(sub.ptr)
+	runtime.KeepAlive(sub)
 	return SubmoduleUpdate(o)
 }
 
@@ -250,6 +277,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_set_update(c.repo.ptr, csubmodule, C.git_submodule_update_t(update))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -269,6 +297,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_set_fetch_recurse_submodules(c.repo.ptr, csubmodule, C.git_submodule_recurse_t(recurse))
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(C.int(ret))
 	}
@@ -280,6 +309,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_init(sub.ptr, cbool(overwrite))
+	runtime.KeepAlive(sub)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -291,6 +321,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_sync(sub.ptr)
+	runtime.KeepAlive(sub)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -303,6 +334,7 @@
 
 	var ptr *C.git_repository
 	ret := C.git_submodule_open(&ptr, sub.ptr)
+	runtime.KeepAlive(sub)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -320,6 +352,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_submodule_update(sub.ptr, cbool(init), &copts)
+	runtime.KeepAlive(sub)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
diff --git a/tag.go b/tag.go
index 81d7258..a58b090 100644
--- a/tag.go
+++ b/tag.go
@@ -18,22 +18,28 @@
 }
 
 func (t Tag) Message() string {
-	return C.GoString(C.git_tag_message(t.cast_ptr))
+	ret := C.GoString(C.git_tag_message(t.cast_ptr))
+	runtime.KeepAlive(t)
+	return ret
 }
 
 func (t Tag) Name() string {
-	return C.GoString(C.git_tag_name(t.cast_ptr))
+	ret := C.GoString(C.git_tag_name(t.cast_ptr))
+	runtime.KeepAlive(t)
+	return ret
 }
 
 func (t Tag) Tagger() *Signature {
 	cast_ptr := C.git_tag_tagger(t.cast_ptr)
-	return newSignatureFromC(cast_ptr)
+	ret := newSignatureFromC(cast_ptr)
+	runtime.KeepAlive(t)
+	return ret
 }
 
 func (t Tag) Target() *Object {
 	var ptr *C.git_object
 	ret := C.git_tag_target(&ptr, t.cast_ptr)
-
+	runtime.KeepAlive(t)
 	if ret != 0 {
 		return nil
 	}
@@ -42,11 +48,15 @@
 }
 
 func (t Tag) TargetId() *Oid {
-	return newOidFromC(C.git_tag_target_id(t.cast_ptr))
+	ret := newOidFromC(C.git_tag_target_id(t.cast_ptr))
+	runtime.KeepAlive(t)
+	return ret
 }
 
 func (t Tag) TargetType() ObjectType {
-	return ObjectType(C.git_tag_target_type(t.cast_ptr))
+	ret := ObjectType(C.git_tag_target_type(t.cast_ptr))
+	runtime.KeepAlive(t)
+	return ret
 }
 
 type TagsCollection struct {
@@ -76,6 +86,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_tag_create(oid.toC(), c.repo.ptr, cname, ctarget, taggerSig, cmessage, 0)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -91,6 +102,7 @@
 	defer C.free(unsafe.Pointer(cname))
 
 	ret := C.git_tag_delete(c.repo.ptr, cname)
+	runtime.KeepAlive(c)
 	if ret < 0 {
 		return MakeGitError(ret)
 	}
@@ -123,6 +135,7 @@
 	defer runtime.UnlockOSThread()
 
 	err := C.git_tag_create_lightweight(oid.toC(), c.repo.ptr, cname, ctarget, cbool(force))
+	runtime.KeepAlive(c)
 	if err < 0 {
 		return nil, MakeGitError(err)
 	}
@@ -139,6 +152,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_tag_list(&strC, c.repo.ptr)
+	runtime.KeepAlive(c)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -162,6 +176,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_tag_list_match(&strC, patternC, c.repo.ptr)
+	runtime.KeepAlive(c)
 	if ecode < 0 {
 		return nil, MakeGitError(ecode)
 	}
@@ -215,6 +230,7 @@
 	defer runtime.UnlockOSThread()
 
 	err := C._go_git_tag_foreach(c.repo.ptr, handle)
+	runtime.KeepAlive(c)
 	if err == C.GIT_EUSER {
 		return data.err
 	}
diff --git a/tree.go b/tree.go
index 27dd63d..f5cbd78 100644
--- a/tree.go
+++ b/tree.go
@@ -48,6 +48,7 @@
 	defer C.free(unsafe.Pointer(cname))
 
 	entry := C.git_tree_entry_byname(t.cast_ptr, cname)
+	runtime.KeepAlive(t)
 	if entry == nil {
 		return nil
 	}
@@ -66,6 +67,8 @@
 	defer runtime.UnlockOSThread()
 
 	entry := C.git_tree_entry_byid(t.cast_ptr, id.toC())
+	runtime.KeepAlive(t)
+	runtime.KeepAlive(id)
 	if entry == nil {
 		return nil
 	}
@@ -84,6 +87,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_tree_entry_bypath(&entry, t.cast_ptr, cpath)
+	runtime.KeepAlive(t)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
@@ -94,6 +98,7 @@
 
 func (t Tree) EntryByIndex(index uint64) *TreeEntry {
 	entry := C.git_tree_entry_byindex(t.cast_ptr, C.size_t(index))
+	runtime.KeepAlive(t)
 	if entry == nil {
 		return nil
 	}
@@ -103,6 +108,7 @@
 
 func (t Tree) EntryCount() uint64 {
 	num := C.git_tree_entrycount(t.cast_ptr)
+	runtime.KeepAlive(t)
 	return uint64(num)
 }
 
@@ -132,7 +138,7 @@
 		C.GIT_TREEWALK_PRE,
 		ptr,
 	)
-
+	runtime.KeepAlive(t)
 	if err < 0 {
 		return MakeGitError(err)
 	}
@@ -158,6 +164,8 @@
 	defer runtime.UnlockOSThread()
 
 	err := C.git_treebuilder_insert(nil, v.ptr, cfilename, id.toC(), C.git_filemode_t(filemode))
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(id)
 	if err < 0 {
 		return MakeGitError(err)
 	}
@@ -173,6 +181,7 @@
 	defer runtime.UnlockOSThread()
 
 	err := C.git_treebuilder_remove(v.ptr, cfilename)
+	runtime.KeepAlive(v)
 	if err < 0 {
 		return MakeGitError(err)
 	}
@@ -187,7 +196,7 @@
 	defer runtime.UnlockOSThread()
 
 	err := C.git_treebuilder_write(oid.toC(), v.ptr)
-
+	runtime.KeepAlive(v)
 	if err < 0 {
 		return nil, MakeGitError(err)
 	}
diff --git a/walk.go b/walk.go
index ab1de61..287edb6 100644
--- a/walk.go
+++ b/walk.go
@@ -34,6 +34,7 @@
 
 func (v *RevWalk) Reset() {
 	C.git_revwalk_reset(v.ptr)
+	runtime.KeepAlive(v)
 }
 
 func (v *RevWalk) Push(id *Oid) error {
@@ -41,6 +42,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_revwalk_push(v.ptr, id.toC())
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(id)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -55,6 +58,7 @@
 	defer C.free(unsafe.Pointer(cstr))
 
 	ecode := C.git_revwalk_push_glob(v.ptr, cstr)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -69,6 +73,7 @@
 	defer C.free(unsafe.Pointer(cstr))
 
 	ecode := C.git_revwalk_push_range(v.ptr, cstr)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -83,6 +88,7 @@
 	defer C.free(unsafe.Pointer(cstr))
 
 	ecode := C.git_revwalk_push_ref(v.ptr, cstr)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -94,6 +100,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_revwalk_push_head(v.ptr)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		err = MakeGitError(ecode)
 	}
@@ -105,6 +112,8 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_revwalk_hide(v.ptr, id.toC())
+	runtime.KeepAlive(v)
+	runtime.KeepAlive(id)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -119,6 +128,7 @@
 	defer C.free(unsafe.Pointer(cstr))
 
 	ecode := C.git_revwalk_hide_glob(v.ptr, cstr)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -133,6 +143,7 @@
 	defer C.free(unsafe.Pointer(cstr))
 
 	ecode := C.git_revwalk_hide_ref(v.ptr, cstr)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		return MakeGitError(ecode)
 	}
@@ -144,6 +155,7 @@
 	defer runtime.UnlockOSThread()
 
 	ecode := C.git_revwalk_hide_head(v.ptr)
+	runtime.KeepAlive(v)
 	if ecode < 0 {
 		err = MakeGitError(ecode)
 	}
@@ -155,6 +167,7 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_revwalk_next(id.toC(), v.ptr)
+	runtime.KeepAlive(v)
 	switch {
 	case ret < 0:
 		err = MakeGitError(ret)
@@ -192,14 +205,15 @@
 
 func (v *RevWalk) SimplifyFirstParent() {
 	C.git_revwalk_simplify_first_parent(v.ptr)
+	runtime.KeepAlive(v)
 }
 
 func (v *RevWalk) Sorting(sm SortType) {
 	C.git_revwalk_sorting(v.ptr, C.uint(sm))
+	runtime.KeepAlive(v)
 }
 
 func (v *RevWalk) Free() {
-
 	runtime.SetFinalizer(v, nil)
 	C.git_revwalk_free(v.ptr)
 }