#define FEAT_PROCESS_STR_FUN(__feat, __feat_env) \
 static int process_##__feat(struct feat_fd *ff, void *data __maybe_unused) \
 {\
+       free(ff->ph->env.__feat_env);                \
        ff->ph->env.__feat_env = do_read_string(ff); \
        return ff->ph->env.__feat_env ? 0 : -ENOMEM; \
 }
        struct perf_record_header_feature *fe = (struct perf_record_header_feature *)event;
        int type = fe->header.type;
        u64 feat = fe->feat_id;
+       int ret = 0;
 
        if (type < 0 || type >= PERF_RECORD_HEADER_MAX) {
                pr_warning("invalid record type %d in pipe-mode\n", type);
        ff.size = event->header.size - sizeof(*fe);
        ff.ph = &session->header;
 
-       if (feat_ops[feat].process(&ff, NULL))
-               return -1;
+       if (feat_ops[feat].process(&ff, NULL)) {
+               ret = -1;
+               goto out;
+       }
 
        if (!feat_ops[feat].print || !tool->show_feat_hdr)
-               return 0;
+               goto out;
 
        if (!feat_ops[feat].full_only ||
            tool->show_feat_hdr >= SHOW_FEAT_HEADER_FULL_INFO) {
                fprintf(stdout, "# %s info available, use -I to display\n",
                        feat_ops[feat].name);
        }
-
-       return 0;
+out:
+       free_event_desc(ff.events);
+       return ret;
 }
 
 size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)