}
        sizeClassBuckets = make([]float64, _NumSizeClasses)
        for i := range sizeClassBuckets {
-               sizeClassBuckets[i] = float64(class_to_size[i])
+               // Size classes have an inclusive upper-bound
+               // and exclusive lower bound (e.g. 48-byte size class is
+               // (32, 48]) whereas we want and inclusive lower-bound
+               // and exclusive upper-bound (e.g. 48-byte size class is
+               // [33, 49). We can achieve this by shifting all bucket
+               // boundaries up by 1.
+               //
+               // Also, a float64 can precisely represent integers with
+               // value up to 2^53 and size classes are relatively small
+               // (nowhere near 2^48 even) so this will give us exact
+               // boundaries.
+               sizeClassBuckets[i] = float64(class_to_size[i] + 1)
        }
        timeHistBuckets = timeHistogramMetricsBuckets()
        metrics = map[string]metricData{
 
        if totalVirtual.got != totalVirtual.want {
                t.Errorf(`"/memory/classes/total:bytes" does not match sum of /memory/classes/**: got %d, want %d`, totalVirtual.got, totalVirtual.want)
        }
+       if objects.alloc.Counts[0] > 0 {
+               t.Error("found counts for objects of non-positive size in allocs-by-size")
+       }
+       if objects.free.Counts[0] > 0 {
+               t.Error("found counts for objects of non-positive size in frees-by-size")
+       }
        if len(objects.alloc.Buckets) != len(objects.free.Buckets) {
                t.Error("allocs-by-size and frees-by-size buckets don't match in length")
        } else if len(objects.alloc.Counts) != len(objects.free.Counts) {