From 17a1447ad09a19e737be4c2a2aaff1929df9cd9c Mon Sep 17 00:00:00 2001 From: VNovitski Date: Mon, 6 Apr 2015 18:24:39 +0300 Subject: [PATCH 1/4] MSVC compatibility for vsprintf. --- linear.cpp | 6 +++++- tron.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/linear.cpp b/linear.cpp index 302e1e1..7f2b140 100644 --- a/linear.cpp +++ b/linear.cpp @@ -30,13 +30,17 @@ static void print_string_stdout(const char *s) static void (*liblinear_print_string) (const char *) = &print_string_stdout; +#ifdef _MSC_VER +#pragma warning (disable:4996) // 'vsnprintf': This function or variable may be unsafe. +#endif // _MSC_VER + #if 1 static void info(const char *fmt,...) { char buf[BUFSIZ]; va_list ap; va_start(ap,fmt); - vsprintf(buf,fmt,ap); + vsnprintf(buf,BUFSIZ,fmt,ap); va_end(ap); (*liblinear_print_string)(buf); } diff --git a/tron.cpp b/tron.cpp index 7d1fd6e..c559cee 100644 --- a/tron.cpp +++ b/tron.cpp @@ -12,6 +12,10 @@ template static inline T min(T x,T y) { return (x static inline T max(T x,T y) { return (x>y)?x:y; } #endif +#ifdef _MSC_VER +#pragma warning (disable:4996) // 'vsnprintf': This function or variable may be unsafe. +#endif // _MSC_VER + #ifdef __cplusplus extern "C" { #endif @@ -36,7 +40,7 @@ void TRON::info(const char *fmt,...) char buf[BUFSIZ]; va_list ap; va_start(ap,fmt); - vsprintf(buf,fmt,ap); + vsnprintf(buf,BUFSIZ,fmt,ap); va_end(ap); (*tron_print_string)(buf); } From 439744dd39cdc33e6db1790ec173a3c45b63de6d Mon Sep 17 00:00:00 2001 From: VNovitski Date: Mon, 6 Apr 2015 21:00:38 +0300 Subject: [PATCH 2/4] Consistent and memory safe buffer allocation. --- linear.cpp | 313 ++++++++++++++++++++---------------------------- linear.h | 3 + memory_buffer.h | 78 ++++++++++++ tron.cpp | 21 ++-- 4 files changed, 218 insertions(+), 197 deletions(-) create mode 100644 memory_buffer.h diff --git a/linear.cpp b/linear.cpp index 7f2b140..4d3f0b9 100644 --- a/linear.cpp +++ b/linear.cpp @@ -6,6 +6,8 @@ #include #include "linear.h" #include "tron.h" +#include "memory_buffer.h" + typedef signed char schar; template static inline void swap(T& x, T& y) { T t=x; x=y; y=t; } #ifndef min @@ -19,9 +21,22 @@ template static inline void clone(T*& dst, S* src, int n) dst = new T[n]; memcpy((void *)dst,(void *)src,sizeof(T)*n); } -#define Malloc(type,n) (type *)malloc((n)*sizeof(type)) #define INF HUGE_VAL +model::model() +{ + ::memset( this, 0, sizeof( *this ) ); +} +model::~model() +{ + delete[] w; + delete[] label; + + w = 0; + label = 0; +} + + static void print_string_stdout(const char *s) { fputs(s,stdout); @@ -65,8 +80,8 @@ class l2r_lr_fun: public function void XTv(double *v, double *XTv); double *C; - double *z; - double *D; + CBuffer z; + CBuffer D; const problem *prob; }; @@ -76,15 +91,13 @@ l2r_lr_fun::l2r_lr_fun(const problem *prob, double *C) this->prob = prob; - z = new double[l]; - D = new double[l]; + z.Realloc(l); + D.Realloc(l); this->C = C; } l2r_lr_fun::~l2r_lr_fun() { - delete[] z; - delete[] D; } @@ -142,7 +155,7 @@ void l2r_lr_fun::Hv(double *s, double *Hs) int i; int l=prob->l; int w_size=get_nr_variable(); - double *wa = new double[l]; + CBuffer wa(l); Xv(s, wa); for(i=0;i z; + CBuffer D; + CBuffer I; int sizeI; const problem *prob; }; @@ -223,17 +235,14 @@ l2r_l2_svc_fun::l2r_l2_svc_fun(const problem *prob, double *C) this->prob = prob; - z = new double[l]; - D = new double[l]; - I = new int[l]; + z.Realloc(l); + D.Realloc(l); + I.Realloc(l); this->C = C; } l2r_l2_svc_fun::~l2r_l2_svc_fun() { - delete[] z; - delete[] D; - delete[] I; } double l2r_l2_svc_fun::fun(double *w) @@ -290,7 +299,7 @@ void l2r_l2_svc_fun::Hv(double *s, double *Hs) { int i; int w_size=get_nr_variable(); - double *wa = new double[sizeI]; + CBuffer wa(sizeI); subXv(s, wa); for(i=0;i B; + double *C; + CBuffer G; int w_size, l; int nr_class; int max_iter; @@ -482,15 +492,13 @@ Solver_MCSVM_CS::Solver_MCSVM_CS(const problem *prob, int nr_class, double *weig this->eps = eps; this->max_iter = max_iter; this->prob = prob; - this->B = new double[nr_class]; - this->G = new double[nr_class]; + this->B.Realloc(nr_class); + this->G.Realloc(nr_class); this->C = weighted_C; } Solver_MCSVM_CS::~Solver_MCSVM_CS() { - delete[] B; - delete[] G; } int compare_double(const void *a, const void *b) @@ -507,7 +515,7 @@ void Solver_MCSVM_CS::solve_sub_problem(double A_i, int yi, double C_yi, int act int r; double *D; - clone(D, B, active_i); + clone(D, B.Ptr(), active_i); if(yi < active_i) D[yi] += A_i*C_yi; qsort(D, active_i, sizeof(double), compare_double); @@ -541,16 +549,16 @@ void Solver_MCSVM_CS::Solve(double *w) { int i, m, s; int iter = 0; - double *alpha = new double[l*nr_class]; - double *alpha_new = new double[nr_class]; - int *index = new int[l]; - double *QD = new double[l]; - int *d_ind = new int[nr_class]; - double *d_val = new double[nr_class]; - int *alpha_index = new int[nr_class*l]; - int *y_index = new int[l]; + CBuffer alpha(l*nr_class); + CBuffer alpha_new(nr_class); + CBuffer index(l); + CBuffer QD(l); + CBuffer d_ind(nr_class); + CBuffer d_val(nr_class); + CBuffer alpha_index(nr_class*l); + CBuffer y_index(l); int active_size = l; - int *active_size_i = new int[l]; + CBuffer active_size_i(l); double eps_shrink = max(10.0*eps, 1.0); // stopping tolerance for shrinking bool start_from_all = true; @@ -737,16 +745,6 @@ void Solver_MCSVM_CS::Solve(double *w) v -= alpha[i*nr_class+(int)prob->y[i]]; info("Objective value = %lf\n",v); info("nSV = %d\n",nSV); - - delete [] alpha; - delete [] alpha_new; - delete [] index; - delete [] QD; - delete [] d_ind; - delete [] d_val; - delete [] alpha_index; - delete [] y_index; - delete [] active_size_i; } // A coordinate descent algorithm for @@ -787,11 +785,11 @@ static void solve_l2r_l1l2_svc( int w_size = prob->n; int i, s, iter = 0; double C, d, G; - double *QD = new double[l]; + CBuffer QD(l); int max_iter = 1000; - int *index = new int[l]; - double *alpha = new double[l]; - schar *y = new schar[l]; + CBuffer index(l); + CBuffer alpha(l); + CBuffer y(l); int active_size = l; // PG: projected gradient, for shrinking and stopping @@ -961,11 +959,6 @@ static void solve_l2r_l1l2_svc( } info("Objective value = %lf\n",v/2); info("nSV = %d\n",nSV); - - delete [] QD; - delete [] alpha; - delete [] y; - delete [] index; } @@ -1009,14 +1002,14 @@ static void solve_l2r_l1l2_svr( int i, s, iter = 0; int max_iter = 1000; int active_size = l; - int *index = new int[l]; + CBuffer index(l); double d, G, H; double Gmax_old = INF; double Gmax_new, Gnorm1_new; double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration - double *beta = new double[l]; - double *QD = new double[l]; + CBuffer beta(l); + CBuffer QD(l); double *y = prob->y; // L2R_L2LOSS_SVR_DUAL @@ -1195,10 +1188,6 @@ static void solve_l2r_l1l2_svr( info("Objective value = %lf\n", v); info("nSV = %d\n",nSV); - - delete [] beta; - delete [] QD; - delete [] index; } @@ -1229,11 +1218,11 @@ void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, do int l = prob->l; int w_size = prob->n; int i, s, iter = 0; - double *xTx = new double[l]; + CBuffer xTx(l); int max_iter = 1000; - int *index = new int[l]; - double *alpha = new double[2*l]; // store alpha and C - alpha - schar *y = new schar[l]; + CBuffer index(l); + CBuffer alpha(2*l); // store alpha and C - alpha + CBuffer y(l); int max_inner_iter = 100; // for inner Newton double innereps = 1e-2; double innereps_min = min(1e-8, eps); @@ -1374,11 +1363,6 @@ void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, do v += alpha[2*i] * log(alpha[2*i]) + alpha[2*i+1] * log(alpha[2*i+1]) - upper_bound[GETI(i)] * log(upper_bound[GETI(i)]); info("Objective value = %lf\n", v); - - delete [] xTx; - delete [] alpha; - delete [] y; - delete [] index; } // A coordinate descent algorithm for @@ -1418,10 +1402,10 @@ static void solve_l1r_l2_svc( double loss_old, loss_new; double appxcond, cond; - int *index = new int[w_size]; - schar *y = new schar[l]; - double *b = new double[l]; // b = 1-ywTx - double *xj_sq = new double[w_size]; + CBuffer index(w_size); + CBuffer y(l); + CBuffer b(l); // b = 1-ywTx + CBuffer xj_sq(w_size); feature_node *x; double C[3] = {Cn,0,Cp}; @@ -1661,11 +1645,6 @@ static void solve_l1r_l2_svc( info("Objective value = %lf\n", v); info("#nonzeros/#features = %d/%d\n", nnz, w_size); - - delete [] index; - delete [] y; - delete [] b; - delete [] xj_sq; } // A coordinate descent algorithm for @@ -1710,17 +1689,17 @@ static void solve_l1r_lr( double QP_Gmax_new, QP_Gnorm1_new; double delta, negsum_xTd, cond; - int *index = new int[w_size]; - schar *y = new schar[l]; - double *Hdiag = new double[w_size]; - double *Grad = new double[w_size]; - double *wpd = new double[w_size]; - double *xjneg_sum = new double[w_size]; - double *xTd = new double[l]; - double *exp_wTx = new double[l]; - double *exp_wTx_new = new double[l]; - double *tau = new double[l]; - double *D = new double[l]; + CBuffer index(w_size); + CBuffer y(l); + CBuffer Hdiag(w_size); + CBuffer Grad(w_size); + CBuffer wpd(w_size); + CBuffer xjneg_sum(w_size); + CBuffer xTd(l); + CBuffer exp_wTx(l); + CBuffer exp_wTx_new(l); + CBuffer tau(l); + CBuffer D(l); feature_node *x; double C[3] = {Cn,0,Cp}; @@ -2035,18 +2014,6 @@ static void solve_l1r_lr( info("Objective value = %lf\n", v); info("#nonzeros/#features = %d/%d\n", nnz, w_size); - - delete [] index; - delete [] y; - delete [] Hdiag; - delete [] Grad; - delete [] wpd; - delete [] xjneg_sum; - delete [] xTd; - delete [] exp_wTx; - delete [] exp_wTx_new; - delete [] tau; - delete [] D; } // transpose matrix X from row format to column format @@ -2056,7 +2023,7 @@ static void transpose(const problem *prob, feature_node **x_space_ret, problem * int l = prob->l; int n = prob->n; size_t nnz = 0; - size_t *col_ptr = new size_t [n+1]; + CBuffer col_ptr(n+1); feature_node *x_space; prob_col->l = l; prob_col->n = n; @@ -2101,20 +2068,19 @@ static void transpose(const problem *prob, feature_node **x_space_ret, problem * x_space[col_ptr[i]].index = -1; *x_space_ret = x_space; - - delete [] col_ptr; } // label: label name, start: begin of each class, count: #data of classes, perm: indices to the original data // perm, length l, must be allocated before calling this subroutine -static void group_classes(const problem *prob, int *nr_class_ret, int **label_ret, int **start_ret, int **count_ret, int *perm) +static void group_classes(const problem *prob, int *nr_class_ret, + CBuffer& label, CBuffer& start, CBuffer& count, int *perm) { int l = prob->l; int max_nr_class = 16; int nr_class = 0; - int *label = Malloc(int,max_nr_class); - int *count = Malloc(int,max_nr_class); - int *data_label = Malloc(int,l); + label.Realloc(max_nr_class); + count.Realloc(max_nr_class); + CBuffer data_label(l); int i; for(i=0;il; - function *fun_obj=NULL; switch(param->solver_type) { case L2R_LR: { - double *C = new double[prob->l]; + CBuffer C(prob->l); for(int i = 0; i < prob->l; i++) { if(prob->y[i] > 0) @@ -2207,17 +2168,15 @@ static void train_one(const problem *prob, const parameter *param, double *w, do else C[i] = Cn; } - fun_obj=new l2r_lr_fun(prob, C); - TRON tron_obj(fun_obj, primal_solver_tol); + l2r_lr_fun fun_obj(prob, C); + TRON tron_obj(&fun_obj, primal_solver_tol); tron_obj.set_print_string(liblinear_print_string); tron_obj.tron(w); - delete fun_obj; - delete[] C; break; } case L2R_L2LOSS_SVC: { - double *C = new double[prob->l]; + CBuffer C(prob->l); for(int i = 0; i < prob->l; i++) { if(prob->y[i] > 0) @@ -2225,12 +2184,10 @@ static void train_one(const problem *prob, const parameter *param, double *w, do else C[i] = Cn; } - fun_obj=new l2r_l2_svc_fun(prob, C); - TRON tron_obj(fun_obj, primal_solver_tol); + l2r_l2_svc_fun fun_obj(prob, C); + TRON tron_obj(&fun_obj, primal_solver_tol); tron_obj.set_print_string(liblinear_print_string); tron_obj.tron(w); - delete fun_obj; - delete[] C; break; } case L2R_L2LOSS_SVC_DUAL: @@ -2266,16 +2223,14 @@ static void train_one(const problem *prob, const parameter *param, double *w, do break; case L2R_L2LOSS_SVR: { - double *C = new double[prob->l]; + CBuffer C(prob->l); for(int i = 0; i < prob->l; i++) C[i] = param->C; - fun_obj=new l2r_l2_svr_fun(prob, C, param->p); - TRON tron_obj(fun_obj, param->eps); + l2r_l2_svr_fun fun_obj(prob, C, param->p); + TRON tron_obj(&fun_obj, param->eps); tron_obj.set_print_string(liblinear_print_string); tron_obj.tron(w); - delete fun_obj; - delete[] C; break; } @@ -2300,7 +2255,7 @@ model* train(const problem *prob, const parameter *param) int l = prob->l; int n = prob->n; int w_size = prob->n; - model *model_ = Malloc(model,1); + CBuffer model_(1); if(prob->bias>=0) model_->nr_feature=n-1; @@ -2311,7 +2266,7 @@ model* train(const problem *prob, const parameter *param) if(check_regression_model(model_)) { - model_->w = Malloc(double, w_size); + model_->w = CBuffer(w_size).Detach(); model_->nr_class = 2; model_->label = NULL; train_one(prob, param, &model_->w[0], 0, 0); @@ -2319,21 +2274,21 @@ model* train(const problem *prob, const parameter *param) else { int nr_class; - int *label = NULL; - int *start = NULL; - int *count = NULL; - int *perm = Malloc(int,l); + CBuffer label; + CBuffer start; + CBuffer count; + CBuffer perm(l); // group training data of the same class - group_classes(prob,&nr_class,&label,&start,&count,perm); + group_classes(prob,&nr_class,label,start,count,perm); model_->nr_class=nr_class; - model_->label = Malloc(int,nr_class); + model_->label = CBuffer(nr_class).Detach(); for(i=0;ilabel[i] = label[i]; // calculate weighted C - double *weighted_C = Malloc(double, nr_class); + CBuffer weighted_C(nr_class); for(i=0;iC; for(i=0;inr_weight;i++) @@ -2348,16 +2303,18 @@ model* train(const problem *prob, const parameter *param) } // constructing the subproblem - feature_node **x = Malloc(feature_node *,l); + CBuffer x(l); for(i=0;ix[perm[i]]; int k; + CBuffer sub_prob_x_buffer(l); + CBuffer sub_prob_y_buffer(l); problem sub_prob; sub_prob.l = l; sub_prob.n = n; - sub_prob.x = Malloc(feature_node *,sub_prob.l); - sub_prob.y = Malloc(double,sub_prob.l); + sub_prob.x = sub_prob_x_buffer; + sub_prob.y = sub_prob_y_buffer; for(k=0; ksolver_type == MCSVM_CS) { - model_->w=Malloc(double, n*nr_class); + model_->w=CBuffer(n*nr_class).Detach(); for(i=0;iw=Malloc(double, w_size); + model_->w=CBuffer(w_size).Detach(); int e0 = start[0]+count[0]; k=0; @@ -2389,8 +2346,8 @@ model* train(const problem *prob, const parameter *param) } else { - model_->w=Malloc(double, w_size*nr_class); - double *w=Malloc(double, w_size); + model_->w=CBuffer(w_size*nr_class).Detach(); + CBuffer w(w_size); for(i=0;iw[j*nr_class+i] = w[j]; } - free(w); } } - free(x); - free(label); - free(start); - free(count); - free(perm); - free(sub_prob.x); - free(sub_prob.y); - free(weighted_C); } - return model_; + return model_.Detach(); } void cross_validation(const problem *prob, const parameter *param, int nr_fold, double *target) { int i; - int *fold_start; + CBuffer fold_start; int l = prob->l; - int *perm = Malloc(int,l); + CBuffer perm(l); if (nr_fold > l) { nr_fold = l; fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n"); } - fold_start = Malloc(int,nr_fold+1); + fold_start.Realloc(nr_fold+1); for(i=0;i subprob_x_buffer(examples_count); + CBuffer subprob_y_buffer(examples_count); subprob.bias = prob->bias; subprob.n = prob->n; - subprob.l = l-(end-begin); - subprob.x = Malloc(struct feature_node*,subprob.l); - subprob.y = Malloc(double,subprob.l); + subprob.l = examples_count; + subprob.x = subprob_x_buffer; + subprob.y = subprob_y_buffer; k=0; for(j=0;jx[perm[j]]); free_and_destroy_model(&submodel); - free(subprob.x); - free(subprob.y); } - free(fold_start); - free(perm); } double predict_values(const struct model *model_, const struct feature_node *x, double *dec_values) @@ -2533,9 +2480,8 @@ double predict_values(const struct model *model_, const struct feature_node *x, double predict(const model *model_, const feature_node *x) { - double *dec_values = Malloc(double, model_->nr_class); + CBuffer dec_values(model_->nr_class); double label=predict_values(model_, x, dec_values); - free(dec_values); return label; } @@ -2646,7 +2592,7 @@ struct model *load_model(const char *model_file_name) int n; int nr_class; double bias; - model *model_ = Malloc(model,1); + CBuffer model_(1); parameter& param = model_->param; model_->label = NULL; @@ -2675,8 +2621,6 @@ struct model *load_model(const char *model_file_name) fprintf(stderr,"unknown solver type.\n"); setlocale(LC_ALL, old_locale); - free(model_->label); - free(model_); free(old_locale); return NULL; } @@ -2703,7 +2647,7 @@ struct model *load_model(const char *model_file_name) else if(strcmp(cmd,"label")==0) { int nr_class = model_->nr_class; - model_->label = Malloc(int,nr_class); + model_->label = CBuffer(nr_class).Detach(); for(int i=0;ilabel[i]); } @@ -2711,8 +2655,6 @@ struct model *load_model(const char *model_file_name) { fprintf(stderr,"unknown text in model file: [%s]\n",cmd); setlocale(LC_ALL, old_locale); - free(model_->label); - free(model_); free(old_locale); return NULL; } @@ -2730,7 +2672,7 @@ struct model *load_model(const char *model_file_name) else nr_w = nr_class; - model_->w=Malloc(double, w_size*nr_w); + model_->w=CBuffer(w_size*nr_w).Detach(); for(i=0; iw != NULL) - free(model_ptr->w); - if(model_ptr->label != NULL) - free(model_ptr->label); + if(model_ptr->w != NULL) { + delete[] model_ptr->w; + model_ptr->w = 0; + } + if(model_ptr->label != NULL) { + delete[] model_ptr->label; + model_ptr->label = 0; + } } void free_and_destroy_model(struct model **model_ptr_ptr) @@ -2825,7 +2771,8 @@ void free_and_destroy_model(struct model **model_ptr_ptr) if(model_ptr != NULL) { free_model_content(model_ptr); - free(model_ptr); + delete model_ptr; + *model_ptr_ptr = 0; } } diff --git a/linear.h b/linear.h index 6b07b47..0f22325 100644 --- a/linear.h +++ b/linear.h @@ -42,6 +42,9 @@ struct model double *w; int *label; /* label of each class */ double bias; + + model(); + ~model(); }; struct model* train(const struct problem *prob, const struct parameter *param); diff --git a/memory_buffer.h b/memory_buffer.h new file mode 100644 index 0000000..ba86724 --- /dev/null +++ b/memory_buffer.h @@ -0,0 +1,78 @@ +#ifndef _MEMORY_BUFFER +#define _MEMORY_BUFFER + +#include + +// Simple memory buffer for RAII +template +class CBuffer { +public: + CBuffer() : count( 0 ), ptr( 0 ) {} + explicit CBuffer( size_t count ); + ~CBuffer(); + + size_t Count() const { return count; } + + TItemType* Detach(); + void Realloc( size_t new_size ); + + TItemType& operator[]( int index ) { assert( ptr != 0 ); return ptr[index]; } + TItemType* operator->() { assert( count == 1 ); return ptr; } + operator TItemType*() { return ptr; } // bad idea, but less code changed + + // Better way, may be in future + TItemType* Ptr() { assert( ptr != 0 ); return ptr; } + +private: + size_t count; + TItemType* ptr; + + // prohibited + CBuffer( const CBuffer& other ); + const CBuffer& operator=( const CBuffer& other ); +}; + +// ---------------------------------------------------------------------------- + +template +inline CBuffer::CBuffer( size_t _count ) : +count( _count ), + ptr( 0 ) +{ + assert( count > 0 ); + ptr = new TItemType[count]; +} + +template +inline CBuffer::~CBuffer() +{ + if( ptr != 0 ) { + delete[] ptr; + ptr = 0; + } +} + +template +inline TItemType* CBuffer::Detach() +{ + TItemType* tmp = ptr; + ptr = 0; + count = 0; + return ptr; +} + +template +inline void CBuffer::Realloc( size_t new_count ) +{ + assert( new_count > count ); + TItemType* buffer = new TItemType[new_count]; + if( count > 0 ) { + ::memcpy( buffer, ptr, count * sizeof( TItemType ) ); + delete[] Detach(); + } + + ptr = buffer; + count = new_count; +} + +#endif // _MEMORY_BUFFER diff --git a/tron.cpp b/tron.cpp index c559cee..6590e08 100644 --- a/tron.cpp +++ b/tron.cpp @@ -3,6 +3,7 @@ #include #include #include "tron.h" +#include "memory_buffer.h" #ifndef min template static inline T min(T x,T y) { return (x s(n); + CBuffer r(n); + CBuffer w_new(n); + CBuffer g(n); for (i=0; iget_nr_variable(); double one = 1; - double *d = new double[n]; - double *Hd = new double[n]; + CBuffer d(n); + CBuffer Hd(n); double rTr, rnewTrnew, alpha, beta, cgtol; for (i=0; i Date: Mon, 6 Apr 2015 23:20:10 +0300 Subject: [PATCH 3/4] [fix] misprint --- memory_buffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory_buffer.h b/memory_buffer.h index ba86724..db7d84d 100644 --- a/memory_buffer.h +++ b/memory_buffer.h @@ -58,7 +58,7 @@ inline TItemType* CBuffer::Detach() TItemType* tmp = ptr; ptr = 0; count = 0; - return ptr; + return tmp; } template From cc8ca00793ed7c381acde9128e8925f5e3bf1f93 Mon Sep 17 00:00:00 2001 From: VNovitski Date: Wed, 8 Apr 2015 12:46:04 +0300 Subject: [PATCH 4/4] [fix] delete[] to match model allocation way. --- linear.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linear.cpp b/linear.cpp index 4d3f0b9..ff9ef1d 100644 --- a/linear.cpp +++ b/linear.cpp @@ -2771,7 +2771,7 @@ void free_and_destroy_model(struct model **model_ptr_ptr) if(model_ptr != NULL) { free_model_content(model_ptr); - delete model_ptr; + delete[] model_ptr; *model_ptr_ptr = 0; } }