00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifdef CURLDEBUG
00026
00027 #include <curl/curl.h>
00028
00029 #include "urldata.h"
00030
00031 #define MEMDEBUG_NODEFINES
00032
00033
00034 #include "curl_printf.h"
00035 #include "curl_memory.h"
00036 #include "memdebug.h"
00037
00038 #ifndef HAVE_ASSERT_H
00039 # define assert(x) Curl_nop_stmt
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #ifdef CURL_MT_MALLOC_FILL
00059 # if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff)
00060 # error "invalid CURL_MT_MALLOC_FILL or out of range"
00061 # endif
00062 #endif
00063
00064 #ifdef CURL_MT_FREE_FILL
00065 # if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff)
00066 # error "invalid CURL_MT_FREE_FILL or out of range"
00067 # endif
00068 #endif
00069
00070 #if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL)
00071 # if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL)
00072 # error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL"
00073 # endif
00074 #endif
00075
00076 #ifdef CURL_MT_MALLOC_FILL
00077 # define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len))
00078 #else
00079 # define mt_malloc_fill(buf,len) Curl_nop_stmt
00080 #endif
00081
00082 #ifdef CURL_MT_FREE_FILL
00083 # define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len))
00084 #else
00085 # define mt_free_fill(buf,len) Curl_nop_stmt
00086 #endif
00087
00088 struct memdebug {
00089 size_t size;
00090 union {
00091 curl_off_t o;
00092 double d;
00093 void *p;
00094 } mem[1];
00095
00096
00097 };
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 #define logfile curl_debuglogfile
00108 FILE *curl_debuglogfile = NULL;
00109 static bool memlimit = FALSE;
00110 static long memsize = 0;
00111
00112
00113 void curl_memdebug(const char *logname)
00114 {
00115 if(!logfile) {
00116 if(logname && *logname)
00117 logfile = fopen(logname, FOPEN_WRITETEXT);
00118 else
00119 logfile = stderr;
00120 #ifdef MEMDEBUG_LOG_SYNC
00121
00122 setbuf(logfile, (char *)NULL);
00123 #endif
00124 }
00125 }
00126
00127
00128
00129 void curl_memlimit(long limit)
00130 {
00131 if(!memlimit) {
00132 memlimit = TRUE;
00133 memsize = limit;
00134 }
00135 }
00136
00137
00138 static bool countcheck(const char *func, int line, const char *source)
00139 {
00140
00141
00142 if(memlimit && source) {
00143 if(!memsize) {
00144 if(source) {
00145
00146 curl_memlog("LIMIT %s:%d %s reached memlimit\n",
00147 source, line, func);
00148
00149 fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
00150 source, line, func);
00151 fflush(logfile);
00152 }
00153 SET_ERRNO(ENOMEM);
00154 return TRUE;
00155 }
00156 else
00157 memsize--;
00158
00159
00160 }
00161
00162 return FALSE;
00163 }
00164
00165 void *curl_domalloc(size_t wantedsize, int line, const char *source)
00166 {
00167 struct memdebug *mem;
00168 size_t size;
00169
00170 assert(wantedsize != 0);
00171
00172 if(countcheck("malloc", line, source))
00173 return NULL;
00174
00175
00176 size = sizeof(struct memdebug)+wantedsize;
00177
00178 mem = (Curl_cmalloc)(size);
00179 if(mem) {
00180
00181 mt_malloc_fill(mem->mem, wantedsize);
00182 mem->size = wantedsize;
00183 }
00184
00185 if(source)
00186 curl_memlog("MEM %s:%d malloc(%zu) = %p\n",
00187 source, line, wantedsize,
00188 mem ? (void *)mem->mem : (void *)0);
00189
00190 return (mem ? mem->mem : NULL);
00191 }
00192
00193 void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
00194 int line, const char *source)
00195 {
00196 struct memdebug *mem;
00197 size_t size, user_size;
00198
00199 assert(wanted_elements != 0);
00200 assert(wanted_size != 0);
00201
00202 if(countcheck("calloc", line, source))
00203 return NULL;
00204
00205
00206 user_size = wanted_size * wanted_elements;
00207 size = sizeof(struct memdebug) + user_size;
00208
00209 mem = (Curl_ccalloc)(1, size);
00210 if(mem)
00211 mem->size = user_size;
00212
00213 if(source)
00214 curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
00215 source, line, wanted_elements, wanted_size,
00216 mem ? (void *)mem->mem : (void *)0);
00217
00218 return (mem ? mem->mem : NULL);
00219 }
00220
00221 char *curl_dostrdup(const char *str, int line, const char *source)
00222 {
00223 char *mem;
00224 size_t len;
00225
00226 assert(str != NULL);
00227
00228 if(countcheck("strdup", line, source))
00229 return NULL;
00230
00231 len=strlen(str)+1;
00232
00233 mem=curl_domalloc(len, 0, NULL);
00234 if(mem)
00235 memcpy(mem, str, len);
00236
00237 if(source)
00238 curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
00239 source, line, (void *)str, len, (void *)mem);
00240
00241 return mem;
00242 }
00243
00244 #if defined(WIN32) && defined(UNICODE)
00245 wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
00246 {
00247 wchar_t *mem;
00248 size_t wsiz, bsiz;
00249
00250 assert(str != NULL);
00251
00252 if(countcheck("wcsdup", line, source))
00253 return NULL;
00254
00255 wsiz = wcslen(str) + 1;
00256 bsiz = wsiz * sizeof(wchar_t);
00257
00258 mem = curl_domalloc(bsiz, 0, NULL);
00259 if(mem)
00260 memcpy(mem, str, bsiz);
00261
00262 if(source)
00263 curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
00264 source, line, (void *)str, bsiz, (void *)mem);
00265
00266 return mem;
00267 }
00268 #endif
00269
00270
00271
00272 void *curl_dorealloc(void *ptr, size_t wantedsize,
00273 int line, const char *source)
00274 {
00275 struct memdebug *mem=NULL;
00276
00277 size_t size = sizeof(struct memdebug)+wantedsize;
00278
00279 assert(wantedsize != 0);
00280
00281 if(countcheck("realloc", line, source))
00282 return NULL;
00283
00284 #ifdef __INTEL_COMPILER
00285 # pragma warning(push)
00286 # pragma warning(disable:1684)
00287
00288 #endif
00289
00290 if(ptr)
00291 mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
00292
00293 #ifdef __INTEL_COMPILER
00294 # pragma warning(pop)
00295 #endif
00296
00297 mem = (Curl_crealloc)(mem, size);
00298 if(source)
00299 curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
00300 source, line, (void *)ptr, wantedsize,
00301 mem ? (void *)mem->mem : (void *)0);
00302
00303 if(mem) {
00304 mem->size = wantedsize;
00305 return mem->mem;
00306 }
00307
00308 return NULL;
00309 }
00310
00311 void curl_dofree(void *ptr, int line, const char *source)
00312 {
00313 struct memdebug *mem;
00314
00315 if(ptr) {
00316
00317 #ifdef __INTEL_COMPILER
00318 # pragma warning(push)
00319 # pragma warning(disable:1684)
00320
00321 #endif
00322
00323 mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
00324
00325 #ifdef __INTEL_COMPILER
00326 # pragma warning(pop)
00327 #endif
00328
00329
00330 mt_free_fill(mem->mem, mem->size);
00331
00332
00333 (Curl_cfree)(mem);
00334 }
00335
00336 if(source)
00337 curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
00338 }
00339
00340 curl_socket_t curl_socket(int domain, int type, int protocol,
00341 int line, const char *source)
00342 {
00343 const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
00344 "FD %s:%d socket() = %d\n" :
00345 (sizeof(curl_socket_t) == sizeof(long)) ?
00346 "FD %s:%d socket() = %ld\n" :
00347 "FD %s:%d socket() = %zd\n";
00348
00349 curl_socket_t sockfd = socket(domain, type, protocol);
00350
00351 if(source && (sockfd != CURL_SOCKET_BAD))
00352 curl_memlog(fmt, source, line, sockfd);
00353
00354 return sockfd;
00355 }
00356
00357 #ifdef HAVE_SOCKETPAIR
00358 int curl_socketpair(int domain, int type, int protocol,
00359 curl_socket_t socket_vector[2],
00360 int line, const char *source)
00361 {
00362 const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
00363 "FD %s:%d socketpair() = %d %d\n" :
00364 (sizeof(curl_socket_t) == sizeof(long)) ?
00365 "FD %s:%d socketpair() = %ld %ld\n" :
00366 "FD %s:%d socketpair() = %zd %zd\n";
00367
00368 int res = socketpair(domain, type, protocol, socket_vector);
00369
00370 if(source && (0 == res))
00371 curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
00372
00373 return res;
00374 }
00375 #endif
00376
00377 curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
00378 int line, const char *source)
00379 {
00380 const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
00381 "FD %s:%d accept() = %d\n" :
00382 (sizeof(curl_socket_t) == sizeof(long)) ?
00383 "FD %s:%d accept() = %ld\n" :
00384 "FD %s:%d accept() = %zd\n";
00385
00386 struct sockaddr *addr = (struct sockaddr *)saddr;
00387 curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
00388
00389 curl_socket_t sockfd = accept(s, addr, addrlen);
00390
00391 if(source && (sockfd != CURL_SOCKET_BAD))
00392 curl_memlog(fmt, source, line, sockfd);
00393
00394 return sockfd;
00395 }
00396
00397
00398 void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
00399 {
00400 const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
00401 "FD %s:%d sclose(%d)\n":
00402 (sizeof(curl_socket_t) == sizeof(long)) ?
00403 "FD %s:%d sclose(%ld)\n":
00404 "FD %s:%d sclose(%zd)\n";
00405
00406 if(source)
00407 curl_memlog(fmt, source, line, sockfd);
00408 }
00409
00410
00411 int curl_sclose(curl_socket_t sockfd, int line, const char *source)
00412 {
00413 int res=sclose(sockfd);
00414 curl_mark_sclose(sockfd, line, source);
00415 return res;
00416 }
00417
00418 FILE *curl_fopen(const char *file, const char *mode,
00419 int line, const char *source)
00420 {
00421 FILE *res=fopen(file, mode);
00422
00423 if(source)
00424 curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
00425 source, line, file, mode, (void *)res);
00426
00427 return res;
00428 }
00429
00430 #ifdef HAVE_FDOPEN
00431 FILE *curl_fdopen(int filedes, const char *mode,
00432 int line, const char *source)
00433 {
00434 FILE *res=fdopen(filedes, mode);
00435
00436 if(source)
00437 curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
00438 source, line, filedes, mode, (void *)res);
00439
00440 return res;
00441 }
00442 #endif
00443
00444 int curl_fclose(FILE *file, int line, const char *source)
00445 {
00446 int res;
00447
00448 assert(file != NULL);
00449
00450 res=fclose(file);
00451
00452 if(source)
00453 curl_memlog("FILE %s:%d fclose(%p)\n",
00454 source, line, (void *)file);
00455
00456 return res;
00457 }
00458
00459 #define LOGLINE_BUFSIZE 1024
00460
00461
00462 void curl_memlog(const char *format, ...)
00463 {
00464 char *buf;
00465 int nchars;
00466 va_list ap;
00467
00468 if(!logfile)
00469 return;
00470
00471 buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
00472 if(!buf)
00473 return;
00474
00475 va_start(ap, format);
00476 nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
00477 va_end(ap);
00478
00479 if(nchars > LOGLINE_BUFSIZE - 1)
00480 nchars = LOGLINE_BUFSIZE - 1;
00481
00482 if(nchars > 0)
00483 fwrite(buf, 1, nchars, logfile);
00484
00485 (Curl_cfree)(buf);
00486 }
00487
00488 #endif