From ec68838342b42541776607b0c14e40fb89f7e3d8 Mon Sep 17 00:00:00 2001
From: AlexeyAB <alexeyab84@gmail.com>
Date: Wed, 23 May 2018 15:27:18 +0000
Subject: [PATCH] Fixed memory leaks for Yolo: train, test

---
 src/demo.c                    |   27 +++++++++++++
 src/layer.c                   |    1 
 src/convolutional_layer.c     |    2 
 src/list.c                    |   12 ++++++
 src/detector.c                |   30 +++++++++++---
 src/list.h                    |    1 
 build/darknet/darknet.vcxproj |    5 +-
 src/utils.c                   |    8 ++-
 8 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/build/darknet/darknet.vcxproj b/build/darknet/darknet.vcxproj
index bc4b82d..8fbf93c 100644
--- a/build/darknet/darknet.vcxproj
+++ b/build/darknet/darknet.vcxproj
@@ -89,9 +89,10 @@
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
       <AdditionalIncludeDirectories>C:\opencv_3.0\opencv\build\include;..\..\3rdparty\include;%(AdditionalIncludeDirectories);$(CudaToolkitIncludeDir);$(cudnn)\include</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;_MBCS;_TIMESPEC_DEFINED;_CRT_SECURE_NO_WARNINGS;_CRT_RAND_S;GPU;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <UndefinePreprocessorDefinitions>CUDNN;OPENCV;</UndefinePreprocessorDefinitions>
+      <PreprocessorDefinitions>CUDNN;_CRTDBG_MAP_ALLOC;_MBCS;_TIMESPEC_DEFINED;_CRT_SECURE_NO_WARNINGS;_CRT_RAND_S;GPU;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <UndefinePreprocessorDefinitions>OPENCV;</UndefinePreprocessorDefinitions>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <ForcedIncludeFiles>stdlib.h;crtdbg.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
diff --git a/src/convolutional_layer.c b/src/convolutional_layer.c
index f4a5d89..90f9551 100644
--- a/src/convolutional_layer.c
+++ b/src/convolutional_layer.c
@@ -502,7 +502,7 @@
 	size_t total_byte;
 	check_error(cudaMemGetInfo(&free_byte, &total_byte));
 	if (l->workspace_size > free_byte || l->workspace_size >= total_byte / 2) {
-		printf(" used slow CUDNN algo without Workspace! Need memory: %d, available: %d\n", l->workspace_size, (free_byte < total_byte/2) ? free_byte : total_byte/2);
+		printf(" used slow CUDNN algo without Workspace! Need memory: %zu, available: %zu\n", l->workspace_size, (free_byte < total_byte/2) ? free_byte : total_byte/2);
 		cudnn_convolutional_setup(l, cudnn_smallest);
 		l->workspace_size = get_workspace_size(*l);
 	}
diff --git a/src/demo.c b/src/demo.c
index 3452706..81eddb2 100644
--- a/src/demo.c
+++ b/src/demo.c
@@ -312,6 +312,33 @@
 		cvReleaseVideoWriter(&output_video_writer);
 		printf("output_video_writer closed. \n");
 	}
+
+	// free memory
+	cvReleaseImage(&show_img);
+	cvReleaseImage(&in_img);
+	free_image(in_s);
+
+	free(avg);
+	for (j = 0; j < FRAMES; ++j) free(predictions[j]);
+	for (j = 0; j < FRAMES; ++j) free_image(images[j]);
+
+	for (j = 0; j < l.w*l.h*l.n; ++j) free(probs[j]);
+	free(boxes);
+	free(probs);
+
+	free_ptrs(names, net.layers[net.n - 1].classes);
+
+	int i;
+	const int nsize = 8;
+	for (j = 0; j < nsize; ++j) {
+		for (i = 32; i < 127; ++i) {
+			free_image(alphabet[j][i]);
+		}
+		free(alphabet[j]);
+	}
+	free(alphabet);
+
+	free_network(net);
 }
 #else
 void demo(char *cfgfile, char *weightfile, float thresh, float hier_thresh, int cam_index, const char *filename, char **names, int classes,
diff --git a/src/detector.c b/src/detector.c
index 8b53907..536b9d7 100644
--- a/src/detector.c
+++ b/src/detector.c
@@ -1,8 +1,3 @@
-#ifdef _DEBUG
-#include <stdlib.h> 
-#include <crtdbg.h>  
-#endif
-
 #include "network.h"
 #include "region_layer.h"
 #include "cost_layer.h"
@@ -221,8 +216,25 @@
     sprintf(buff, "%s/%s_final.weights", backup_directory, base);
     save_weights(net, buff);
 
-	//cvReleaseImage(&img);
-	//cvDestroyAllWindows();
+#ifdef OPENCV
+	cvReleaseImage(&img);
+	cvDestroyAllWindows();
+#endif
+
+	// free memory
+	pthread_join(load_thread, 0);
+	free_data(buffer);
+
+	free(base);
+	free(paths);
+	free_list_contents(plist);
+	free_list(plist);
+
+	free_list_contents_kvp(options);
+	free_list(options);
+
+	free(nets);
+	free_network(net);
 }
 
 
@@ -1150,6 +1162,7 @@
 
 	// free memory
 	free_ptrs(names, net.layers[net.n - 1].classes);
+	free_list_contents_kvp(options);
 	free_list(options);
 
 	int i;
@@ -1236,6 +1249,9 @@
 				if (filename[strlen(filename) - 1] == 0x0d) filename[strlen(filename) - 1] = 0;
         demo(cfg, weights, thresh, hier_thresh, cam_index, filename, names, classes, frame_skip, prefix, out_filename,
 			http_stream_port, dont_show, ext_output);
+
+		free_list_contents_kvp(options);
+		free_list(options);
     }
 	else printf(" There isn't such command: %s", argv[2]);
 }
diff --git a/src/layer.c b/src/layer.c
index 582cbb3..3b47917 100644
--- a/src/layer.c
+++ b/src/layer.c
@@ -11,6 +11,7 @@
 #endif
 		return;
 	}
+	if (l.mask)               free(l.mask);
 	if (l.cweights)           free(l.cweights);
 	if (l.indexes)            free(l.indexes);
 	if (l.input_layers)       free(l.input_layers);
diff --git a/src/list.c b/src/list.c
index 0e4165d..e83f63e 100644
--- a/src/list.c
+++ b/src/list.c
@@ -1,6 +1,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "list.h"
+#include "option_list.h"
 
 list *make_list()
 {
@@ -79,6 +80,17 @@
 	}
 }
 
+void free_list_contents_kvp(list *l)
+{
+	node *n = l->front;
+	while (n) {
+		kvp *p = n->val;
+		free(p->key);
+		free(n->val);
+		n = n->next;
+	}
+}
+
 void **list_to_array(list *l)
 {
     void **a = calloc(l->size, sizeof(void*));
diff --git a/src/list.h b/src/list.h
index fb818c2..c06d142 100644
--- a/src/list.h
+++ b/src/list.h
@@ -22,5 +22,6 @@
 
 void free_list(list *l);
 void free_list_contents(list *l);
+void free_list_contents_kvp(list *l);
 
 #endif
diff --git a/src/utils.c b/src/utils.c
index fe89eb0..7b25e9c 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -175,6 +175,7 @@
     sprintf(buffer, "%s", str);
     if(!(p = strstr(buffer, orig))){  // Is 'orig' even in 'str'?
         sprintf(output, "%s", str);
+		free(buffer);
         return;
     }
 
@@ -194,6 +195,7 @@
 	int chars_from_end = strlen(buffer) - offset;
 	if (!p || chars_from_end != strlen(orig)) {  // Is 'orig' even in 'str' AND is 'orig' found at the end of 'str'?
 		sprintf(output, "%s", str);
+		free(buffer);
 		return;
 	}
 
@@ -206,13 +208,13 @@
 void replace_image_to_label(char *input_path, char *output_path) {
 	//find_replace(input_path, "images", "labels", output_path);	// COCO
 	find_replace(input_path, "images/train2014/", "labels/train2014/", output_path);	// COCO
-	find_replace(input_path, "images/val2014/", "labels/val2014/", output_path);		// COCO
+	find_replace(output_path, "images/val2014/", "labels/val2014/", output_path);		// COCO
 	//find_replace(output_path, "JPEGImages", "labels", output_path);	// PascalVOC
 	find_replace(output_path, "VOC2007/JPEGImages", "VOC2007/labels", output_path);		// PascalVOC
 	find_replace(output_path, "VOC2012/JPEGImages", "VOC2012/labels", output_path);		// PascalVOC
 	// replace only ext of files
 	find_replace_extension(output_path, ".jpg", ".txt", output_path);
-	find_replace_extension(output_path, ".JPG", ".txt", output_path);
+	find_replace_extension(output_path, ".JPG", ".txt", output_path); // error
 	find_replace_extension(output_path, ".jpeg", ".txt", output_path);
 	find_replace_extension(output_path, ".JPEG", ".txt", output_path);
 	find_replace_extension(output_path, ".png", ".txt", output_path);
@@ -285,7 +287,7 @@
     size_t offset = 0;
     for(i = 0; i < len; ++i){
         char c = s[i];
-        if(c==' '||c=='\t'||c=='\n'||c =='\r') ++offset;
+        if(c==' '||c=='\t'||c=='\n'||c =='\r'||c==0x0d||c==0x0a) ++offset;
         else s[i-offset] = c;
     }
     s[len-offset] = '\0';

--
Gitblit v1.10.0