On Fri May 02 08:01:53 2014, SREZIC wrote:
Show quoted text
The problem is that the code writes over its arguments without ensuring they're not COWed, so for example:
above_thres_in_window => [sub { my $a = shift; my @r = $a->[0]; # Reserve space
int_sum_window($a->[0], $r[0], shift, shift);
\@r}, 'above_thres', 'chunks', 'above_thres_window']
copies $a->[0] into $r[0], which with COW means that both $a->[0] and $r[0] share the same buffer, and when int_sum_window() writes to $r[0]'s buffer, it ends up writing over $a->[0] as well (and any other SVs that share the same buffer.
I've attached a patch that ensures that each output SV is not using a shared buffer, though it makes the XS a lot more verbose unfortunately.
Tony
diff -ru Audio-FindChunks-2.00-orig/FindChunks.xs Audio-FindChunks-2.00/FindChunks.xs
--- Audio-FindChunks-2.00-orig/FindChunks.xs 2008-04-08 19:58:00.000000000 +1000
+++ Audio-FindChunks-2.00/FindChunks.xs 2014-05-14 11:36:37.000000000 +1000
@@ -15,30 +15,55 @@
PROTOTYPES: ENABLE
long
-bool_find_runs(input, output, cnt, out_cnt)
+bool_find_runs(input, output_sv, cnt, out_cnt)
int * input
- array_run_t * output
+ SV * output_sv
long cnt
long out_cnt
-
+ PREINIT:
+ array_run_t * output = (array_run_t *)SvPV_force_nolen(output_sv);
+ CODE:
+ RETVAL = bool_find_runs(input, output, cnt, out_cnt);
+ OUTPUT:
+ RETVAL
+ output_sv
+
void
-double_find_above(input, output, cnt, threshold)
+double_find_above(input, output_sv, cnt, threshold)
double * input
- int * output
+ SV * output_sv
long cnt
double threshold
+ PREINIT:
+ int * output = (int *)SvPV_force_nolen(output_sv);
+ CODE:
+ double_find_above(input, output, cnt, threshold);
+ OUTPUT:
+ output_sv
void
-double_median3(rmsarray, medarray, total_blocks)
+double_median3(rmsarray, medarray_sv, total_blocks)
double * rmsarray
- double * medarray
+ SV * medarray_sv
long total_blocks
+ PREINIT:
+ double * medarray = (double *)SvPV_force_nolen(medarray_sv);
+ CODE:
+ double_median3(rmsarray, medarray, total_blocks);
+ OUTPUT:
+ medarray_sv
void
-double_sort(input, output, cnt)
+double_sort(input, output_sv, cnt)
double * input
- double * output
+ SV * output_sv
long cnt
+ PREINIT:
+ double * output = (double *)SvPV_force_nolen(output_sv);
+ CODE:
+ double_sort(input, output, cnt);
+ OUTPUT:
+ output_sv
double
double_sum(input, off, cnt)
@@ -47,25 +72,43 @@
long cnt
void
-int_find_above(input, output, cnt, threshold)
+int_find_above(input, output_sv, cnt, threshold)
int * input
- int * output
+ SV * output_sv
long cnt
int threshold
+ PREINIT:
+ int * output = (int *)SvPV_force_nolen(output_sv);
+ CODE:
+ int_find_above(input, output, cnt, threshold);
+ OUTPUT:
+ output_sv
void
-int_sum_window(input, output, cnt, window_size)
+int_sum_window(input, output_sv, cnt, window_size)
int * input
- int * output
+ SV * output_sv
long cnt
int window_size
+ PREINIT:
+ int * output = (int *)SvPV_force_nolen(output_sv);
+ CODE:
+ int_sum_window(input, output, cnt, window_size);
+ OUTPUT:
+ output_sv
void
-le_short_sample_stats(buf, stride, samples, stat)
+le_short_sample_stats(buf, stride, samples, stat_sv)
void_char * buf
int stride
long samples
- array_stats_t * stat
+ SV * stat_sv
+ PREINIT:
+ array_stats_t * stat = (array_stats_t *)SvPV_force_nolen(stat_sv);
+ CODE:
+ le_short_sample_stats(buf, stride, samples, stat);
+ OUTPUT:
+ stat_sv
int
_s_size()