0_SH_Leak.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. // leave this as first line for PCH reasons...
  2. //
  3. #pragma warning( disable : 4786)
  4. #pragma warning( disable : 4100)
  5. #pragma warning( disable : 4663)
  6. #include <windows.h>
  7. #include "..\smartheap\smrtheap.h"
  8. #include "../game/q_shared.h"
  9. #include "..\qcommon\qcommon.h"
  10. #include <stdio.h>
  11. #include <map>
  12. using namespace std;
  13. #if MEM_DEBUG
  14. #include "..\smartheap\heapagnt.h"
  15. static const int maxStack=2048;
  16. static int TotalMem;
  17. static int TotalBlocks;
  18. static int nStack;
  19. static char StackNames[maxStack][256];
  20. static int StackSize[maxStack];
  21. static int StackCount[maxStack];
  22. static int StackCache[48];
  23. static int StackCacheAt=0;
  24. static int CheckpointSize[3000];
  25. static int CheckpointCount[3000];
  26. //#define _FASTRPT_
  27. #ifdef _FASTRPT_
  28. class CMyStrComparator
  29. {
  30. public:
  31. bool operator()(const char *s1, const char *s2) const { return(strcmp(s1, s2) < 0); }
  32. };
  33. hmap<const char *,int,CMyStrComparator> Lookup;
  34. #endif
  35. cvar_t *mem_leakfile;
  36. cvar_t *mem_leakreport;
  37. MEM_BOOL MEM_CALLBACK MyMemReporter2(MEM_ERROR_INFO *info)
  38. {
  39. static char buffer[10000];
  40. if (!info->objectCreationInfo)
  41. return 1;
  42. info=info->objectCreationInfo;
  43. int idx=info->checkpoint;
  44. if (idx<0||idx>=1000)
  45. {
  46. idx=0;
  47. }
  48. CheckpointCount[idx]++;
  49. CheckpointSize[idx]+=info->argSize;
  50. dbgMemFormatCall(info,buffer,9999);
  51. if (strstr(buffer,"ntdll"))
  52. return 1;
  53. if (strstr(buffer,"CLBCATQ"))
  54. return 1;
  55. int i;
  56. TotalBlocks++;
  57. if (TotalBlocks%1000==0)
  58. {
  59. char mess[1000];
  60. sprintf(mess,"%d blocks processed\n",TotalBlocks);
  61. OutputDebugString(mess);
  62. }
  63. for (i=strlen(buffer);i>0;i--)
  64. {
  65. if (buffer[i]=='\n')
  66. break;
  67. }
  68. if (!i)
  69. return 1;
  70. buffer[i]=0;
  71. char *buf=buffer;
  72. while (*buf)
  73. {
  74. if (*buf=='\n')
  75. {
  76. buf++;
  77. break;
  78. }
  79. buf++;
  80. }
  81. char *start=0;
  82. char *altName=0;
  83. while (*buf)
  84. {
  85. while (*buf==' ')
  86. buf++;
  87. start=buf;
  88. while (*buf!=0&&*buf!='\n')
  89. buf++;
  90. if (*start)
  91. {
  92. if (*buf)
  93. {
  94. *buf=0;
  95. buf++;
  96. }
  97. if (strlen(start)>255)
  98. start[255]=0;
  99. if (strstr(start,"std::"))
  100. {
  101. altName="std::??";
  102. // start=0;
  103. continue;
  104. }
  105. if (strstr(start,"Malloc"))
  106. {
  107. altName="Malloc??";
  108. start=0;
  109. continue;
  110. }
  111. if (strstr(start,"G_Alloc"))
  112. {
  113. altName="G_Alloc";
  114. start=0;
  115. continue;
  116. }
  117. if (strstr(start,"Hunk_Alloc"))
  118. {
  119. altName="Hunk_Alloc";
  120. start=0;
  121. continue;
  122. }
  123. if (strstr(start,"FS_LoadFile"))
  124. {
  125. altName="FS_LoadFile";
  126. start=0;
  127. continue;
  128. }
  129. if (strstr(start,"CopyString"))
  130. {
  131. altName="CopyString";
  132. start=0;
  133. continue;
  134. }
  135. break;
  136. }
  137. }
  138. if (!start||!*start)
  139. {
  140. start=altName;
  141. if (!start||!*start)
  142. {
  143. start="UNKNOWN";
  144. }
  145. }
  146. #ifdef _FASTRPT_
  147. hmap<const char *,int,CMyStrComparator>::iterator f=Lookup.find(start);
  148. if(f==Lookup.end())
  149. {
  150. strcpy(StackNames[nStack++],start);
  151. Lookup[(const char *)&StackNames[nStack-1]]=nStack-1;
  152. StackSize[nStack-1]=info->argSize;
  153. StackCount[nStack-1]=1;
  154. }
  155. else
  156. {
  157. StackSize[(*f).second]+=info->argSize;
  158. StackCount[(*f).second]++;
  159. }
  160. #else
  161. for (i=0;i<48;i++)
  162. {
  163. if (StackCache[i]<0||StackCache[i]>=nStack)
  164. continue;
  165. if (!strcmpi(start,StackNames[StackCache[i]]))
  166. break;
  167. }
  168. if (i<48)
  169. {
  170. StackSize[StackCache[i]]+=info->argSize;
  171. StackCount[StackCache[i]]++;
  172. }
  173. else
  174. {
  175. for (i=0;i<nStack;i++)
  176. {
  177. if (!strcmpi(start,StackNames[i]))
  178. break;
  179. }
  180. if (i<nStack)
  181. {
  182. StackSize[i]+=info->argSize;
  183. StackCount[i]++;
  184. StackCache[StackCacheAt]=i;
  185. StackCacheAt++;
  186. if (StackCacheAt>=48)
  187. StackCacheAt=0;
  188. }
  189. else if (i<maxStack)
  190. {
  191. strcpy(StackNames[i],start);
  192. StackSize[i]=info->argSize;
  193. StackCount[i]=1;
  194. nStack++;
  195. }
  196. else if (nStack<maxStack)
  197. {
  198. nStack++;
  199. strcpy(StackNames[maxStack-1],"*****OTHER*****");
  200. StackSize[maxStack-1]=info->argSize;
  201. StackCount[maxStack-1]=1;
  202. }
  203. else
  204. {
  205. StackSize[maxStack-1]+=info->argSize;
  206. StackCount[maxStack-1]++;
  207. }
  208. }
  209. #endif
  210. TotalMem+=info->argSize;
  211. return 1;
  212. }
  213. MEM_BOOL MEM_CALLBACK MyMemReporter3(MEM_ERROR_INFO *info)
  214. {
  215. static char buffer[10000];
  216. if (!info->objectCreationInfo)
  217. return 1;
  218. info=info->objectCreationInfo;
  219. int idx=info->checkpoint;
  220. if (idx<0||idx>=3000)
  221. {
  222. idx=0;
  223. }
  224. CheckpointCount[idx]++;
  225. CheckpointSize[idx]+=info->argSize;
  226. dbgMemFormatCall(info,buffer,9999);
  227. int i;
  228. TotalBlocks++;
  229. // if (TotalBlocks%1000==0)
  230. // {
  231. // char mess[1000];
  232. // sprintf(mess,"%d blocks processed\n",TotalBlocks);
  233. // OutputDebugString(mess);
  234. // }
  235. for (i=strlen(buffer);i>0;i--)
  236. {
  237. if (buffer[i]=='\n')
  238. break;
  239. }
  240. if (!i)
  241. return 1;
  242. buffer[i]=0;
  243. char *buf=buffer;
  244. while (*buf)
  245. {
  246. if (*buf=='\n')
  247. {
  248. buf++;
  249. break;
  250. }
  251. buf++;
  252. }
  253. char *start=0;
  254. char *altName=0;
  255. while (*buf)
  256. {
  257. while (*buf==' ')
  258. buf++;
  259. start=buf;
  260. while (*buf!=0&&*buf!='\n')
  261. buf++;
  262. if (*start)
  263. {
  264. if (*buf)
  265. {
  266. *buf=0;
  267. buf++;
  268. }
  269. if (strlen(start)>255)
  270. start[255]=0;
  271. if (strstr(start,"SV_AreaEntities"))
  272. {
  273. altName="SV_AreaEntities??";
  274. start=0;
  275. continue;
  276. }
  277. if (strstr(start,"SV_Trace"))
  278. {
  279. altName="SV_Trace??";
  280. start=0;
  281. continue;
  282. }
  283. if (strstr(start,"SV_PointContents"))
  284. {
  285. altName="SV_PointContents??";
  286. start=0;
  287. continue;
  288. }
  289. if (strstr(start,"CG_Trace"))
  290. {
  291. altName="??";
  292. start=0;
  293. continue;
  294. }
  295. if (strstr(start,"CG_PointContents"))
  296. {
  297. altName="??";
  298. start=0;
  299. continue;
  300. }
  301. /*
  302. if (strstr(start,""))
  303. {
  304. altName="??";
  305. start=0;
  306. continue;
  307. }
  308. if (strstr(start,""))
  309. {
  310. altName="??";
  311. start=0;
  312. continue;
  313. }
  314. */
  315. break;
  316. }
  317. }
  318. if (!start||!*start)
  319. {
  320. start=altName;
  321. if (!start||!*start)
  322. {
  323. start="UNKNOWN";
  324. }
  325. }
  326. #ifdef _FASTRPT_
  327. hmap<const char *,int,CMyStrComparator>::iterator f=Lookup.find(start);
  328. if(f==Lookup.end())
  329. {
  330. strcpy(StackNames[nStack++],start);
  331. Lookup[(const char *)&StackNames[nStack-1]]=nStack-1;
  332. StackSize[nStack-1]=info->argSize;
  333. StackCount[nStack-1]=1;
  334. }
  335. else
  336. {
  337. StackSize[(*f).second]+=info->argSize;
  338. StackCount[(*f).second]++;
  339. }
  340. #else
  341. for (i=0;i<48;i++)
  342. {
  343. if (StackCache[i]<0||StackCache[i]>=nStack)
  344. continue;
  345. if (!strcmpi(start,StackNames[StackCache[i]]))
  346. break;
  347. }
  348. if (i<48)
  349. {
  350. StackSize[StackCache[i]]+=info->argSize;
  351. StackCount[StackCache[i]]++;
  352. }
  353. else
  354. {
  355. for (i=0;i<nStack;i++)
  356. {
  357. if (!strcmpi(start,StackNames[i]))
  358. break;
  359. }
  360. if (i<nStack)
  361. {
  362. StackSize[i]+=info->argSize;
  363. StackCount[i]++;
  364. StackCache[StackCacheAt]=i;
  365. StackCacheAt++;
  366. if (StackCacheAt>=48)
  367. StackCacheAt=0;
  368. }
  369. else if (i<maxStack)
  370. {
  371. strcpy(StackNames[i],start);
  372. StackSize[i]=info->argSize;
  373. StackCount[i]=1;
  374. nStack++;
  375. }
  376. else if (nStack<maxStack)
  377. {
  378. nStack++;
  379. strcpy(StackNames[maxStack-1],"*****OTHER*****");
  380. StackSize[maxStack-1]=info->argSize;
  381. StackCount[maxStack-1]=1;
  382. }
  383. else
  384. {
  385. StackSize[maxStack-1]+=info->argSize;
  386. StackCount[maxStack-1]++;
  387. }
  388. }
  389. #endif
  390. TotalMem+=info->argSize;
  391. return 1;
  392. }
  393. void SH_Checking_f(void);
  394. #endif
  395. class Leakage
  396. {
  397. MEM_POOL MyPool;
  398. public:
  399. Leakage()
  400. {
  401. MyPool = MemInitDefaultPool();
  402. // MemPoolSetSmallBlockSize(MyPool, 16);
  403. MemPoolSetSmallBlockAllocator(MyPool,MEM_SMALL_BLOCK_SH3);
  404. #if MEM_DEBUG
  405. dbgMemSetGuardSize(2);
  406. EnableChecking(100000);
  407. #endif
  408. }
  409. void LeakReport(void)
  410. {
  411. #if MEM_DEBUG
  412. // This just makes sure we have map nodes available without allocation
  413. // during the heap walk (which could be bad).
  414. int i;
  415. #ifdef _FASTRPT_
  416. hlist<int> makeSureWeHaveNodes;
  417. for(i=0;i<5000;i++)
  418. {
  419. makeSureWeHaveNodes.push_back(0);
  420. }
  421. makeSureWeHaveNodes.clear();
  422. Lookup.clear();
  423. #endif
  424. char mess[1000];
  425. int blocks=dbgMemTotalCount();
  426. int mem=dbgMemTotalSize()/1024;
  427. sprintf(mess,"Final Memory Summary %d blocks %d K\n",blocks,mem);
  428. OutputDebugString(mess);
  429. for (i=0;i<3000;i++)
  430. {
  431. CheckpointSize[i]=0;
  432. CheckpointCount[i]=0;
  433. }
  434. TotalMem=0;
  435. TotalBlocks=0;
  436. nStack=0;
  437. MemSetErrorHandler(MyMemReporter2);
  438. dbgMemReportLeakage(NULL,1,1000);
  439. MemSetErrorHandler(MemDefaultErrorHandler);
  440. multimap<int,pair<int,char *> > sortit;
  441. multimap<int,pair<int,char *> >::iterator j;
  442. if (TotalBlocks)
  443. {
  444. // Sort by size.
  445. Sleep(100);
  446. OutputDebugString("**************************************\n");
  447. OutputDebugString("**********Memory Leak Report**********\n");
  448. OutputDebugString("*************** By Size **************\n");
  449. OutputDebugString("**************************************\n");
  450. sprintf(mess,"Actual leakage %d blocks %d K\n",TotalBlocks,TotalMem/1024);
  451. OutputDebugString(mess);
  452. sortit.clear();
  453. for (i=0;i<nStack;i++)
  454. sortit.insert(pair<int,pair<int,char *> >(-StackSize[i],pair<int,char *>(StackCount[i],StackNames[i])));
  455. Sleep(5);
  456. for (j=sortit.begin();j!=sortit.end();j++)
  457. {
  458. sprintf(mess,"%5d KB %6d cnt %s\n",-(*j).first/1024,(*j).second.first,(*j).second.second);
  459. // if (!(-(*j).first/1024))
  460. // break;
  461. Sleep(5);
  462. OutputDebugString(mess);
  463. }
  464. // Sort by count.
  465. Sleep(100);
  466. OutputDebugString("**************************************\n");
  467. OutputDebugString("**********Memory Leak Report**********\n");
  468. OutputDebugString("************** By Count **************\n");
  469. OutputDebugString("**************************************\n");
  470. sprintf(mess,"Actual leakage %d blocks %d K\n",TotalBlocks,TotalMem/1024);
  471. OutputDebugString(mess);
  472. sortit.clear();
  473. for (i=0;i<nStack;i++)
  474. sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
  475. Sleep(5);
  476. for (j=sortit.begin();j!=sortit.end();j++)
  477. {
  478. sprintf(mess,"%5d KB %6d cnt %s\n",(*j).second.first/1024,-(*j).first,(*j).second.second);
  479. // if (!(-(*j).first/1024))
  480. // break;
  481. Sleep(5);
  482. OutputDebugString(mess);
  483. }
  484. }
  485. else
  486. {
  487. OutputDebugString("No Memory Leaks\n");
  488. }
  489. TotalMem=0;
  490. TotalBlocks=0;
  491. nStack=0;
  492. MemSetErrorHandler(MyMemReporter3);
  493. dbgMemReportLeakage(NULL,2001,2001);
  494. MemSetErrorHandler(MemDefaultErrorHandler);
  495. if (TotalBlocks)
  496. {
  497. // Sort by count.
  498. Sleep(100);
  499. OutputDebugString("**************************************\n");
  500. OutputDebugString("SV_PointContents ");
  501. sprintf(mess,"%d Calls.\n",TotalBlocks);
  502. OutputDebugString(mess);
  503. OutputDebugString("**************************************\n");
  504. sortit.clear();
  505. for (i=0;i<nStack;i++)
  506. sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
  507. Sleep(5);
  508. for (j=sortit.begin();j!=sortit.end();j++)
  509. {
  510. sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
  511. Sleep(5);
  512. OutputDebugString(mess);
  513. }
  514. }
  515. TotalMem=0;
  516. TotalBlocks=0;
  517. nStack=0;
  518. MemSetErrorHandler(MyMemReporter3);
  519. dbgMemReportLeakage(NULL,2002,2002);
  520. MemSetErrorHandler(MemDefaultErrorHandler);
  521. if (TotalBlocks)
  522. {
  523. // Sort by count.
  524. Sleep(100);
  525. OutputDebugString("**************************************\n");
  526. OutputDebugString("SV_Trace ");
  527. sprintf(mess,"%d Calls.\n",TotalBlocks);
  528. OutputDebugString(mess);
  529. OutputDebugString("**************************************\n");
  530. sortit.clear();
  531. for (i=0;i<nStack;i++)
  532. sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
  533. Sleep(5);
  534. for (j=sortit.begin();j!=sortit.end();j++)
  535. {
  536. sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
  537. Sleep(5);
  538. OutputDebugString(mess);
  539. }
  540. }
  541. TotalMem=0;
  542. TotalBlocks=0;
  543. nStack=0;
  544. MemSetErrorHandler(MyMemReporter3);
  545. dbgMemReportLeakage(NULL,2003,2003);
  546. MemSetErrorHandler(MemDefaultErrorHandler);
  547. if (TotalBlocks)
  548. {
  549. // Sort by count.
  550. Sleep(100);
  551. OutputDebugString("**************************************\n");
  552. OutputDebugString("SV_AreaEntities ");
  553. sprintf(mess,"%d Calls.\n",TotalBlocks);
  554. OutputDebugString(mess);
  555. OutputDebugString("**************************************\n");
  556. sortit.clear();
  557. for (i=0;i<nStack;i++)
  558. sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
  559. Sleep(5);
  560. for (j=sortit.begin();j!=sortit.end();j++)
  561. {
  562. sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
  563. Sleep(5);
  564. OutputDebugString(mess);
  565. }
  566. }
  567. TotalMem=0;
  568. TotalBlocks=0;
  569. nStack=0;
  570. MemSetErrorHandler(MyMemReporter3);
  571. dbgMemReportLeakage(NULL,2004,2004);
  572. MemSetErrorHandler(MemDefaultErrorHandler);
  573. if (TotalBlocks)
  574. {
  575. // Sort by count.
  576. Sleep(100);
  577. OutputDebugString("**************************************\n");
  578. OutputDebugString("CG_Trace ");
  579. sprintf(mess,"%d Calls.\n",TotalBlocks);
  580. OutputDebugString(mess);
  581. OutputDebugString("**************************************\n");
  582. sortit.clear();
  583. for (i=0;i<nStack;i++)
  584. sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
  585. Sleep(5);
  586. for (j=sortit.begin();j!=sortit.end();j++)
  587. {
  588. sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
  589. Sleep(5);
  590. OutputDebugString(mess);
  591. }
  592. }
  593. TotalMem=0;
  594. TotalBlocks=0;
  595. nStack=0;
  596. MemSetErrorHandler(MyMemReporter3);
  597. dbgMemReportLeakage(NULL,2005,2005);
  598. MemSetErrorHandler(MemDefaultErrorHandler);
  599. if (TotalBlocks)
  600. {
  601. // Sort by count.
  602. Sleep(100);
  603. OutputDebugString("**************************************\n");
  604. OutputDebugString("CG_PointContents ");
  605. sprintf(mess,"%d Calls.\n",TotalBlocks);
  606. OutputDebugString(mess);
  607. OutputDebugString("**************************************\n");
  608. sortit.clear();
  609. for (i=0;i<nStack;i++)
  610. sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
  611. Sleep(5);
  612. for (j=sortit.begin();j!=sortit.end();j++)
  613. {
  614. sprintf(mess,"%7d cnt %s\n",-(*j).first,(*j).second.second);
  615. Sleep(5);
  616. OutputDebugString(mess);
  617. }
  618. }
  619. #if 0 //sw doesn't have the tag stuff
  620. // Sort by size.
  621. Sleep(5);
  622. OutputDebugString("***************************************\n");
  623. OutputDebugString("By Tag, sort: size ********************\n");
  624. OutputDebugString("size(K) count name \n");
  625. OutputDebugString("-----------------------\n");
  626. Sleep(5);
  627. multimap<int,int> sorted;
  628. for (i=0;i<1000;i++)
  629. {
  630. if (CheckpointCount[i])
  631. {
  632. sorted.insert(pair<int,int>(-CheckpointSize[i],i));
  633. }
  634. }
  635. multimap<int,int>::iterator k;
  636. for (k=sorted.begin();k!=sorted.end();k++)
  637. {
  638. sprintf(mess,"%8d %8d %s\n",CheckpointSize[(*k).second]/1024,CheckpointCount[(*k).second],(*k).second>=2?tagDefs[(*k).second-2]:"unknown");
  639. Sleep(5);
  640. OutputDebugString(mess);
  641. }
  642. // Sort by count.
  643. Sleep(5);
  644. OutputDebugString("By Tag, sort: count *******************\n");
  645. OutputDebugString("size(K) count name \n");
  646. OutputDebugString("-----------------------\n");
  647. Sleep(5);
  648. sorted.clear();
  649. for (i=0;i<1000;i++)
  650. {
  651. if (CheckpointCount[i])
  652. {
  653. sorted.insert(pair<int,int>(-CheckpointCount[i],i));
  654. }
  655. }
  656. for (k=sorted.begin();k!=sorted.end();k++)
  657. {
  658. sprintf(mess,"%8d %8d %s\n",CheckpointSize[(*k).second]/1024,CheckpointCount[(*k).second],(*k).second>=2?tagDefs[(*k).second-2]:"unknown");
  659. Sleep(5);
  660. OutputDebugString(mess);
  661. }
  662. #endif
  663. #endif
  664. }
  665. ~Leakage()
  666. {
  667. #if MEM_DEBUG
  668. if (mem_leakfile && mem_leakfile->integer)
  669. {
  670. dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_FILE,"leakage.out");
  671. dbgMemReportLeakage(NULL,1,1);
  672. dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_PROMPT,NULL);
  673. }
  674. if (mem_leakreport && mem_leakreport->integer)
  675. {
  676. LeakReport();
  677. }
  678. #endif
  679. }
  680. #if MEM_DEBUG
  681. void EnableChecking(int x)
  682. {
  683. if (x)
  684. {
  685. dbgMemSetSafetyLevel(MEM_SAFETY_DEBUG);
  686. dbgMemPoolSetCheckFrequency(MyPool, x);
  687. dbgMemSetCheckFrequency(x);
  688. dbgMemDeferFreeing(TRUE);
  689. dbgMemSetDeferQueueLen(50000);
  690. }
  691. else
  692. {
  693. dbgMemSetSafetyLevel(MEM_SAFETY_SOME);
  694. dbgMemDeferFreeing(FALSE);
  695. }
  696. }
  697. #endif
  698. };
  699. static Leakage TheLeakage;
  700. #if MEM_DEBUG
  701. void MEM_Checking_f(void)
  702. {
  703. if (Cmd_Argc() != 2)
  704. {
  705. Com_Printf ("mem_checking <frequency>\n");
  706. return;
  707. }
  708. if (atol(Cmd_Argv(1)) > 0 && atol(Cmd_Argv(1)) < 100)
  709. {
  710. Com_Printf ("mem_checking frequency is too low ( < 100 )\n");
  711. return;
  712. }
  713. TheLeakage.EnableChecking(atol(Cmd_Argv(1)));
  714. }
  715. void MEM_Report_f(void)
  716. {
  717. if (0)
  718. {
  719. dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_FILE,"leakage.out");
  720. dbgMemReportLeakage(NULL,1,1);
  721. dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_PROMPT,NULL);
  722. }
  723. TheLeakage.LeakReport();
  724. }
  725. /*
  726. void myexit(void)
  727. {
  728. TheLeakage.LeakReport();
  729. }
  730. */
  731. void SH_Register(void)
  732. {
  733. Cmd_AddCommand ("mem_checking", MEM_Checking_f);
  734. Cmd_AddCommand ("mem_report", MEM_Report_f);
  735. mem_leakfile = Cvar_Get( "mem_leakfile", "0", 0 );
  736. mem_leakreport = Cvar_Get( "mem_leakreport", "1", 0 );
  737. // atexit(myexit);
  738. }
  739. #endif