ymemory.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * $Id: ymemory.c 24731 2016-06-06 09:09:06Z seb $
4  *
5  * Basic memory check function to prevent memory leak
6  *
7  * - - - - - - - - - License information: - - - - - - - - -
8  *
9  * Copyright (C) 2011 and beyond by Yoctopuce Sarl, Switzerland.
10  *
11  * Yoctopuce Sarl (hereafter Licensor) grants to you a perpetual
12  * non-exclusive license to use, modify, copy and integrate this
13  * file into your software for the sole purpose of interfacing
14  * with Yoctopuce products.
15  *
16  * You may reproduce and distribute copies of this file in
17  * source or object form, as long as the sole purpose of this
18  * code is to interface with Yoctopuce products. You must retain
19  * this notice in the distributed source file.
20  *
21  * You should refer to Yoctopuce General Terms and Conditions
22  * for additional information regarding your rights and
23  * obligations.
24  *
25  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
26  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
27  * WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS
28  * FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO
29  * EVENT SHALL LICENSOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
30  * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA,
31  * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR
32  * SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT
33  * LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR
34  * CONTRIBUTION, OR OTHER SIMILAR COSTS, WHETHER ASSERTED ON THE
35  * BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF
36  * WARRANTY, OR OTHERWISE.
37  *
38  *********************************************************************/
39 
40 #define __FILE_ID__ "ymemory"
41  // do not use microsoft secure string
42 #define _CRT_SECURE_NO_DEPRECATE
43 #define YMEMORY_ALLOW_MALLOC
44 #include "yproto.h"
45 
46 #include <stdlib.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #ifdef WINDOWS_API
50 #include <time.h>
51 #else
52 #include <sys/time.h>
53 #endif
54 
55 
56 #ifdef YSAFE_MEMORY
57 typedef enum{
58  YMEM_NOT_USED=0,
59  YMEM_MALLOCED,
60  YMEM_FREED
61 } YMEM_STATE;
62 
63 typedef struct{
64  YMEM_STATE state;
65  const char *malloc_file;
66  u32 malloc_line;
67  u32 malloc_size;
68  const char *free_file;
69  u32 free_line;
70  void *ptr;
71 } YMEM_ENTRY;
72 
73 YMEM_ENTRY *yMap = NULL;
74 u32 yMapSize = 0;
75 u32 yMapUsed = 0;
76 yCRITICAL_SECTION yMapCS;
77 
78 
79 
80 static void ymemdumpentry(YMEM_ENTRY *entry,const char* prefix)
81 {
82  dbglog("%s %lX: alloc %s:%d of %db, free %s:%d\n",prefix,entry->ptr,entry->malloc_file,entry->malloc_line,entry->malloc_size,entry->free_file,entry->free_line);
83 }
84 
85 
86 static void ymemdump(void)
87 {
88  u32 i;
89  YMEM_ENTRY *entry;
90  u32 total,count;
91 
92  dbglog("ySafeMemoryDump: %d/%d entry\n\n", yMapUsed, yMapSize);
93  dbglog("Malloc:\n");
94  total=count=0;
95  for(i=0, entry=yMap; i< yMapUsed ; i++,entry++){
96  if(entry->state == YMEM_MALLOCED){
97  ymemdumpentry(entry,"");
98  dbglog("%s : %d of %db (0x%x)\n", entry->malloc_file, entry->malloc_line, entry->malloc_size, entry->ptr);
99  total+= entry->malloc_size;
100  count++;
101  }
102  }
103  dbglog("total: %db (%d Kb) on %d entry\n\n",total,(int)(total/1024),count);
104 #if 0
105  dbglog("Free:\n");
106  for(i=0, entry=yMap; i< yMapUsed ; i++,entry++){
107  if(entry->state == YMEM_FREED){
108  dbglog("alloc %s:%d of %db, free %s:%d\n",entry->malloc_file,entry->malloc_line,entry->malloc_size,entry->free_file,entry->free_line);
109  }
110  }
111 #endif
112 }
113 
114 
115 
116 void ySafeMemoryInit(u32 nbentry)
117 {
118  YASSERT(yMap==NULL);
119  YASSERT(yMapSize==0);
121  yEnterCriticalSection(&yMapCS);
122  yMap = malloc(nbentry *sizeof(YMEM_ENTRY));
123  if(yMap){
124  yMapSize = nbentry;
125  memset(yMap,0,nbentry *sizeof(YMEM_ENTRY));
126  yMapUsed=0;
127  }
128  yLeaveCriticalSection(&yMapCS);
129 }
130 
131 void *ySafeMalloc(const char *file,u32 line,u32 size)
132 {
133  u32 i;
134  YMEM_ENTRY *entry;
135  void *ptr;
136 
137  yEnterCriticalSection(&yMapCS);
138  if(yMapUsed < yMapSize){
139  //use a new one
140  entry=yMap+yMapUsed;
141  }else{
142  // find a freed entry
143  for(i=0; i< yMapSize;i++){
144  if(yMap[i].state == YMEM_FREED)
145  break;
146  }
147  if(i==yMapSize){
148  dbglog("No more entry available for ySafeMalloc\n\n");
149  ymemdump();
150  yLeaveCriticalSection(&yMapCS);
151  return NULL;
152  }
153  entry = yMap+i;
154  }
155 
156  ptr=malloc(size);
157  if(!ptr){
158  dbglog("No more memory available (unable to allocate %d bytes)\n\n",size);
159  ymemdump();
160  yLeaveCriticalSection(&yMapCS);
161  return NULL;
162  }
163 
164  memset(entry,0,sizeof(YMEM_ENTRY));
165  entry->state = YMEM_MALLOCED;
166  entry->malloc_file = file;
167  entry->malloc_line = line;
168  entry->ptr = ptr;
169  entry->malloc_size = size;
170  if(yMapUsed < yMapSize)
171  yMapUsed++;
172  yLeaveCriticalSection(&yMapCS);
173 
174  return ptr;
175 }
176 
177 void ySafeFree(const char *file,u32 line,void *ptr)
178 {
179  u32 i;
180  YMEM_ENTRY *entry;
181 
182  yEnterCriticalSection(&yMapCS);
183  for(i=0, entry=yMap; i< yMapUsed ; i++,entry++){
184  YASSERT(entry->state != YMEM_NOT_USED);
185  if(entry->ptr == ptr)
186  break;
187  }
188  if(i == yMapUsed){
189  dbglog("Free of unallocated pointer 0x%x at %s:%d\n\n",ptr,file,line);
190  ymemdump();
191  YASSERT(0);
192  }
193  if(entry->state == YMEM_FREED){
194  dbglog("Free of allready freed pointer (0x%x) at %s:%d\n",ptr,file,line);
195  dbglog("was allocated at %s:%d size =%d freed at %s:%d\n\n",
196  entry->malloc_file, entry->malloc_line, entry->malloc_size, entry->free_file,entry->free_line);
197  ymemdump();
198  YASSERT(0);
199  }
200  free(entry->ptr);
201  entry->free_file = file;
202  entry->free_line = line;
203  entry->state = YMEM_FREED;
204  entry->ptr=NULL;
205 
206  yLeaveCriticalSection(&yMapCS);
207 }
208 
209 void ySafeTrace(const char *file,u32 line,void *ptr)
210 {
211  u32 i;
212  YMEM_ENTRY *entry;
213 
214  yEnterCriticalSection(&yMapCS);
215  for(i=0, entry=yMap; i< yMapUsed ; i++,entry++){
216  YASSERT(entry->state != YMEM_NOT_USED);
217  if(entry->ptr == ptr)
218  break;
219  }
220  if(i == yMapUsed){
221  dbglog("Update trace of unallocated pointer 0x%x at %s:%d\n\n",ptr,file,line);
222  ymemdump();
223  YASSERT(0);
224  }
225  if(entry->state == YMEM_FREED){
226  dbglog("Update trace of allready freed pointer (0x%x) at %s:%d\n",ptr,file,line);
227  dbglog("was allocated at %s:%d size =%d freed at %s:%d\n\n",
228  entry->malloc_file, entry->malloc_line, entry->malloc_size, entry->free_file,entry->free_line);
229  ymemdump();
230  YASSERT(0);
231  }
232  ymemdumpentry(entry,"trace");
233  entry->malloc_file = file;
234  entry->malloc_line = line;
235  yLeaveCriticalSection(&yMapCS);
236 }
237 
238 void ySafeMemoryDump(void *discard)
239 {
240  u32 i;
241  YMEM_ENTRY *entry;
242 
243  yEnterCriticalSection(&yMapCS);
244  for(i=0, entry=yMap; i< yMapUsed ; i++,entry++){
245  if(entry->state == YMEM_MALLOCED && entry->ptr!=discard){
246  break;
247  }
248  }
249  if(i< yMapUsed){
250  ymemdump();
251  } else {
252  dbglog("No memory leak detected\n");
253  }
254  yLeaveCriticalSection(&yMapCS);
255 }
256 
257 
258 void ySafeMemoryStop(void)
259 {
260  yDeleteCriticalSection(&yMapCS);
261  free(yMap);
262  yMap=NULL;
263  yMapSize = yMapUsed = 0;
264 }
265 
266 #endif
267 
268 
269 // return the min of strlen and maxlen
270 static unsigned ystrnlen(const char *src,unsigned maxlen)
271 {
272  unsigned len;
273  for (len=0 ; *src && len < maxlen ;len++,src++);
274  return len;
275 }
276 
277 YRETCODE ystrcpy_s(char *dst, unsigned dstsize,const char *src)
278 {
279 
280  return ystrncpy_s(dst,dstsize,src,dstsize);
281 }
282 
283 
284 char* ystrdup_s(const char *src)
285 {
286  int len = YSTRLEN(src);
287  char *tmp = yMalloc(len+1);
288  memcpy(tmp, src, len + 1);
289  return tmp;
290 }
291 
292 
293 YRETCODE ystrcat_s(char *dst, unsigned dstsize,const char *src)
294 {
295  return ystrncat_s(dst, dstsize, src, dstsize);
296 }
297 
298 int ysprintf_s(char *dst, unsigned dstsize,const char *fmt ,...)
299 {
300  int len;
301  va_list args;
302  va_start( args, fmt );
303  len = yvsprintf_s(dst,dstsize,fmt,args);
304  va_end(args);
305  return len;
306 }
307 
308 YRETCODE ystrncpy_s(char *dst,unsigned dstsize,const char *src,unsigned arglen)
309 {
310  unsigned len;
311 
312  if (dst==NULL){
313  YPANIC;
314  return YAPI_INVALID_ARGUMENT;
315  }
316  if (src==NULL){
317  YPANIC;
318  return YAPI_INVALID_ARGUMENT;
319  }
320  if(dstsize ==0){
321  YPANIC;
322  return YAPI_INVALID_ARGUMENT;
323  }
324  len = ystrnlen(src,arglen);
325  if(len+1 > dstsize){
326  YPANIC;
327  dst[0]=0;
328  return YAPI_INVALID_ARGUMENT;
329  }else{
330  memcpy(dst,src,len);
331  dst[len]=0;
332  }
333  return YAPI_SUCCESS;
334 }
335 
336 
337 YRETCODE ystrncat_s(char *dst, unsigned dstsize,const char *src,unsigned len)
338 {
339  unsigned dstlen;
340  if (dst==NULL){
341  YPANIC;
342  return YAPI_INVALID_ARGUMENT;
343  }
344  if (src==NULL){
345  YPANIC;
346  return YAPI_INVALID_ARGUMENT;
347  }
348  dstlen = ystrnlen(dst, dstsize);
349  if(dstlen+1 > dstsize){
350  YPANIC;
351  return YAPI_INVALID_ARGUMENT;
352  }
353  return ystrncpy_s(dst+dstlen, dstsize-dstlen, src, len);
354 }
355 
356 
357 int yvsprintf_s (char *dst, unsigned dstsize, const char * fmt, va_list arg )
358 {
359  int len;
360 #if defined(_MSC_VER) && (_MSC_VER <= MSC_VS2003)
361  len = _vsnprintf(dst,dstsize,fmt,arg);
362 #else
363  len = vsnprintf(dst,dstsize,fmt,arg);
364 #endif
365  if(len <0 || len >=(long)dstsize){
366  YPANIC;
367  dst[dstsize-1]=0;
368  return YAPI_INVALID_ARGUMENT;
369  }
370  return len;
371 }
372 
373 int ymemfind(const u8 *haystack, u32 haystack_len, const u8 *needle, u32 needle_len)
374 {
375  u32 abspos = 0;
376  u32 needle_pos = 0;
377 
378  do {
379  while (needle_pos < needle_len && (abspos + needle_pos)<haystack_len && needle[needle_pos] == haystack[abspos + needle_pos]) {
380  needle_pos++;
381  }
382  if (needle_pos == needle_len) {
383  return abspos;
384  } else {
385  abspos++;
386  needle_pos = 0;
387  }
388  } while (abspos + needle_len < haystack_len);
389  return -1;
390 }
391 
392 
static unsigned ystrnlen(const char *src, unsigned maxlen)
Definition: ymemory.c:270
#define ySafeMemoryStop()
Definition: ymemory.h:54
void * yCRITICAL_SECTION
Definition: ydef.h:366
void yInitializeCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:629
YRETCODE ystrncat_s(char *dst, unsigned dstsize, const char *src, unsigned len)
Definition: ymemory.c:337
int yvsprintf_s(char *dst, unsigned dstsize, const char *fmt, va_list arg)
Definition: ymemory.c:357
#define dbglog(args...)
Definition: yproto.h:413
void yLeaveCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:672
char * ystrdup_s(const char *src)
Definition: ymemory.c:284
#define YPANIC
Definition: yproto.h:453
YRETCODE
Definition: ydef.h:376
int ysprintf_s(char *dst, unsigned dstsize, const char *fmt,...)
Definition: ymemory.c:298
#define ySafeMemoryInit(nbentry)
Definition: ymemory.h:52
#define YASSERT(x)
Definition: yproto.h:454
YRETCODE ystrncpy_s(char *dst, unsigned dstsize, const char *src, unsigned arglen)
Definition: ymemory.c:308
#define ySafeMemoryDump(discard)
Definition: ymemory.h:53
void yEnterCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:647
#define yMalloc(size)
Definition: yproto.h:198
#define YSTRLEN(str)
Definition: yproto.h:230
void yDeleteCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:682
int ymemfind(const u8 *haystack, u32 haystack_len, const u8 *needle, u32 needle_len)
Definition: ymemory.c:373
YRETCODE ystrcat_s(char *dst, unsigned dstsize, const char *src)
Definition: ymemory.c:293
YRETCODE ystrcpy_s(char *dst, unsigned dstsize, const char *src)
Definition: ymemory.c:277


yoctopuce_altimeter
Author(s): Anja Sheppard
autogenerated on Mon Jun 10 2019 15:49:10