Second round of keep-alives
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/repository.go b/repository.go
index 44d18a9..6b07e87 100644
--- a/repository.go
+++ b/repository.go
@@ -160,12 +160,11 @@
 	defer runtime.UnlockOSThread()
 
 	ret := C.git_repository_index(&ptr, v.ptr)
-	runtime.KeepAlive(v)
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
 
-	return newIndexFromC(ptr), nil
+	return newIndexFromC(ptr, v), nil
 }
 
 func (v *Repository) lookupType(id *Oid, t ObjectType) (*Object, error) {