Skip to content

additional memory clear helper to the SDK. #243

Description

@v0lkan

we are not using it, and since it's reflection-based could have minimal performance hit; but it is (mostly) possible to clear any type.

func ClearAny(v interface{}) {
	if v == nil {
		return
	}
	
	val := reflect.ValueOf(v)
	if val.Kind() == reflect.Ptr {
		if val.IsNil() {
			return
		}
		val = val.Elem()
	}
	
	clearValue(val)
}

func clearValue(v reflect.Value) {
	if !v.CanAddr() {
		return
	}
	
	switch v.Kind() {
	case reflect.Slice:
		// Clear the backing array
		if v.Len() > 0 {
			elemType := v.Type().Elem()
			if elemType.Kind() == reflect.Uint8 {
				// Fast path for []byte
				ClearBytes(v.Bytes())
			} else {
				// Clear each element
				for i := 0; i < v.Len(); i++ {
					clearValue(v.Index(i))
				}
			}
		}
		// Clear the slice header itself
		clearRawMemory(v.Addr().Interface())
		
	case reflect.Array:
		// Clear each element
		for i := 0; i < v.Len(); i++ {
			clearValue(v.Index(i))
		}
		
	case reflect.Struct:
		// Recursively clear each field
		for i := 0; i < v.NumField(); i++ {
			field := v.Field(i)
			if field.CanAddr() {
				clearValue(field)
			}
		}
		
	case reflect.Map:
		// Maps are tricky - we can't directly clear the backing store
		// Best we can do is delete all entries and clear the header
		for _, key := range v.MapKeys() {
			v.SetMapIndex(key, reflect.Value{})
		}
		clearRawMemory(v.Addr().Interface())
		
	case reflect.Ptr:
		if !v.IsNil() {
			clearValue(v.Elem())
			// Clear the pointer itself
			clearRawMemory(v.Addr().Interface())
		}
		
	case reflect.Interface:
		if !v.IsNil() {
			clearValue(v.Elem())
			// Clear the interface header
			clearRawMemory(v.Addr().Interface())
		}
		
	case reflect.Chan:
		// Can't clear channel buffer safely, just clear the header
		clearRawMemory(v.Addr().Interface())
		
	default:
		// For basic types (int, float, bool, string, etc.)
		clearRawMemory(v.Addr().Interface())
	}
}

func clearRawMemory(ptr interface{}) {
	v := reflect.ValueOf(ptr).Elem()
	size := v.Type().Size()
	
	p := unsafe.Pointer(v.UnsafeAddr())
	b := (*[1 << 30]byte)(p)[:size:size]
	
	for i := range b {
		b[i] = 0
	}
	
	runtime.KeepAlive(ptr)
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions