ref: ffac1116a84af63c88e1addd3a342c9fc3ee503e
parent: 338273aba970352de84eb5ea3278cd4f64689f72
author: Ulrich Klauer <ulrich@chirlu.de>
date: Wed Jan 11 13:50:56 EST 2012
Dynamically allocate user_effargs argv array Instead of using an array of FILENAME_MAX elements for storing the arguments to effects within the user_effargs table, allocate memory as needed. This reduces memory usage greatly in the majority of cases (when the number of arguments is much less than FILENAME_MAX) while allowing more than FILENAME_MAX arguments in exceptional cases. For illustration, here are the valgrind memcheck heap usage statistics for a fairly complex SoX command line involving three effects chains with a total of twelve effects (on my 64-bit Linux system): before: 361 allocs, 356 frees, 3,223,206 bytes allocated after: 367 allocs, 362 frees, 1,815,254 bytes allocated
--- a/src/sox.c
+++ b/src/sox.c
@@ -173,10 +173,11 @@
static sox_effects_chain_t *effects_chain = NULL;
static sox_effect_t *save_output_eff = NULL;
-static struct { char *name; int argc; char *argv[FILENAME_MAX]; } **user_effargs = NULL;
+static struct { char *name; int argc; char **argv; size_t argv_size; } **user_effargs = NULL;
static size_t *user_effargs_size = NULL; /* array: size of user_effargs for each chain */
-/* user_effargs[i] size to be extended in steps of USER_EFFARGS_STEP */
-#define USER_EFFARGS_STEP 8
+/* Size of memory structures related to effects arguments (user_effargs[i],
+ * user_effargs[i][j].argv) to be extended in steps of EFFARGS_STEP */
+#define EFFARGS_STEP 8
static unsigned *nuser_effects = NULL; /* array: number of effects in each chain */
static int current_eff_chain = 0;
static int eff_chain_count = 0;
@@ -738,6 +739,9 @@
user_effargs[eff_chain_count][j].argv[k] = NULL;
}
user_effargs[eff_chain_count][j].argc = 0;
+ free(user_effargs[eff_chain_count][j].argv);
+ user_effargs[eff_chain_count][j].argv = NULL;
+ user_effargs[eff_chain_count][j].argv_size = 0;
}
nuser_effects[eff_chain_count] = 0;
free(user_effargs[eff_chain_count]);
@@ -771,13 +775,18 @@
{
while (optstate.ind < argc) {
unsigned eff_offset;
- int j;
+ size_t j;
int newline_mode = 0;
eff_offset = nuser_effects[eff_chain_count];
if (eff_offset == user_effargs_size[eff_chain_count]) {
- user_effargs_size[eff_chain_count] += USER_EFFARGS_STEP;
+ size_t i = user_effargs_size[eff_chain_count];
+ user_effargs_size[eff_chain_count] += EFFARGS_STEP;
lsx_revalloc(user_effargs[eff_chain_count], user_effargs_size[eff_chain_count]);
+ for (; i < user_effargs_size[eff_chain_count]; i++) {
+ user_effargs[eff_chain_count][i].argv = NULL;
+ user_effargs[eff_chain_count][i].argv_size = 0;
+ }
}
/* pseudo-effect ":" is used to create a new effects chain */
@@ -827,9 +836,15 @@
/* Name should always be correct! */
user_effargs[eff_chain_count][eff_offset].name = lsx_strdup(argv[optstate.ind]);
optstate.ind++;
- for (j = 0; j < argc - optstate.ind && !sox_find_effect(argv[optstate.ind + j]) &&
- !is_pseudo_effect(argv[optstate.ind + j]); ++j)
+ for (j = 0; j < (size_t)(argc - optstate.ind) && !sox_find_effect(argv[optstate.ind + j]) &&
+ !is_pseudo_effect(argv[optstate.ind + j]); ++j) {
+ if (j >= user_effargs[eff_chain_count][eff_offset].argv_size) {
+ user_effargs[eff_chain_count][eff_offset].argv_size += EFFARGS_STEP;
+ lsx_revalloc(user_effargs[eff_chain_count][eff_offset].argv,
+ user_effargs[eff_chain_count][eff_offset].argv_size);
+ }
user_effargs[eff_chain_count][eff_offset].argv[j] = lsx_strdup(argv[optstate.ind + j]);
+ }
user_effargs[eff_chain_count][eff_offset].argc = j;
optstate.ind += j; /* Skip past the effect arguments */