以下内容旨在获取一个可变长度的常量char,并以一种很好的格式打印出来以进行日志记录。 我相信读者会对如何改进这方面提出建议,我对此表示欢迎。
令我困惑的是,我希望每次调用ToHexString()时都需要free()返回的静态char。 相反,我认为没有任何内存泄漏。 即使我使用内联函数,因此也不会将其返回值赋给变量。
我创建了一个简单的测试,在循环中调用此函数,每次使用不同长度的cString和nMaxChars参数。 然后我看了VM的状态。 我的测试程序和可用内存的内存分配从未改变。
在我看来,每次调用malloc并且没有空闲时它应该增加。
static char *ToHexString(const char *cString,int nMaxChars) { static char *cStr; /*if (80>strlen(cString)) nRawChars=strlen(cString); if (nMaxChars>nRawChars) nRawChars=nMaxChars; */ if (nMaxChars==0) nMaxChars=80; printf("There are %i charsn",nMaxChars); char *cStr1; char *cStr2; char *cStr3; int nLen=nMaxChars*6; cStr=calloc(nLen,sizeof(char)); cStr1=calloc(10,sizeof(char)); cStr2=calloc(nLen,sizeof(char)); cStr3=calloc(nLen,sizeof(char)); cStr1[0]=' '; cStr2[0]=' '; cStr3[0]=' '; int nC1=0; int nRowCnt=0; for (nC1=0;nC1<nMaxChars;nC1++) { ++nRowCnt; if (cString[nC1]==0x00) snprintf(cStr1,8,"[00] "); else snprintf(cStr1,8,"[%02x] ",(unsigned char)cString[nC1]); if ( (nRowCnt%8==0) ) { snprintf(cStr3,nLen,"%s%sn",cStr2,cStr1); } else snprintf(cStr3,nLen,"%s%s",cStr2,cStr1); snprintf(cStr2,nLen,"%s",cStr3); } snprintf(cStr,nLen,"%s",cStr3); free(cStr1); free(cStr2); free(cStr3); return(cStr); }
这是调用例程:
for (i=0;i<100;i++) { memset(&cBuff, 0,255); printf("Reading %s now..n",cPort); while (sleep(1)==-1); nChars=read(nPort, cBuff, 255); //printf("Read %i chars from %sn",nChars,cPort); if (nChars<=0) printf("Read 0 chars from %sn",cPort); else printf("Read %i chars from %sn%sn",nChars,cPort,ToHexString(cBuff,nChars)); }
以下是泄漏:
static void memeat(void) { static char *foo = NULL; foo = malloc(1024); return; }
Valgrind输出:
==16167== LEAK SUMMARY: ==16167== definitely lost: 4,096 bytes in 4 blocks ==16167== indirectly lost: 0 bytes in 0 blocks ==16167== possibly lost: 0 bytes in 0 blocks ==16167== still reachable: 1,024 bytes in 1 blocks ==16167== suppressed: 0 bytes in 0 blocks ==16167== Rerun with --leak-check=full to see details of leaked memory
注意, still reachable
(1024字节)是上次输入memeat()
结果。 静态指针仍保持对程序退出时分配的最后一个块memeat()
的有效引用。 只是不是以前的块。
以下不是泄漏:
static void memeat(void) { static char *foo = NULL; foo = realloc(foo, 1024); return; }
Valgrind输出:
==16244== LEAK SUMMARY: ==16244== definitely lost: 0 bytes in 0 blocks ==16244== indirectly lost: 0 bytes in 0 blocks ==16244== possibly lost: 0 bytes in 0 blocks ==16244== still reachable: 1,024 bytes in 1 blocks ==16244== suppressed: 0 bytes in 0 blocks ==16244== Rerun with --leak-check=full to see details of leaked memory
这里,指向的地址foo
已被释放, foo
现在指向新分配的地址,并且在下次输入memeat()
时将继续这样做。
说明:
static
存储类型表示每次输入函数时指针foo
将指向与初始化时相同的地址。 但是,如果每次通过malloc()
或calloc()
输入函数时更改该地址,则会丢失对先前分配的块的引用。 因此,泄漏,因为要么将返回一个新地址。
valgrind中的“仍然可访问”意味着所有已分配的堆块仍然具有在退出时访问/操作/释放它们的有效指针。 这类似于在main()
分配内存而不释放内存,只是依靠操作系统来回收内存。
简而言之,是的 – 你有泄漏。 但是,您可以轻松地修复它。 请注意,你确实依赖你的操作系统来回收内存,除非你向你的函数添加另一个参数,它告诉ToHexString
在静态指针上调用free,你可以在退出时使用它。
与此类似:(完整的测试程序)
#include static void memeat(unsigned int dofree) { static char *foo = NULL; if (dofree == 1 && foo != NULL) { free(foo); return; } foo = realloc(foo, 1024); return; } int main(void) { unsigned int i; for (i = 0; i < 5; i ++) memeat(0); memeat(1); return 0; }
Valgrind输出:
==16285== HEAP SUMMARY: ==16285== in use at exit: 0 bytes in 0 blocks ==16285== total heap usage: 6 allocs, 6 frees, 6,144 bytes allocated ==16285== ==16285== All heap blocks were freed -- no leaks are possible
关于最终输出的注意事项 :
是的,根据malloc()
在程序运行时返回的内容实际分配了6144个字节,但这只是意味着释放了静态指针,然后根据输入memeat()
的次数重新分配。 程序在任何给定时间的实际堆使用实际上只有2 * 1024,1k用于分配新指针,而旧指针仍然存在等待复制到新指针。
同样,调整代码应该不会太难,但我不清楚为什么你开始使用静态存储。
这是一个内存泄漏。 如果持续调用该函数,程序使用的内存会增加。 例如:
int main() { while (1) { ToHexString("testing the function", 20); } }
如果您运行此操作并使用系统监视工具观察该过程,您将看到已使用的内存不断增加。
泄漏在您的程序中可能并不明显,因为该函数每次调用只泄漏几个字节,并且不经常调用。 因此,内存使用量的增加并不是很明显。
在检查代码时,我想指出两个让我头脑发热的东西:
CSTR =释放calloc(nLen,的sizeof(char)的);
为什么你没有对此进行错误检查….正如我从代码中看到的那样,对假设存储器始终可用的零检查….危险…. 始终检查返回时的NULL指针一个内存分配函数调用,如calloc
, malloc
和realloc
……它总是成为程序员的责任,可以管理free
指针以将它们返回堆中。
另外,因为你已经将cStr
声明为char *
的静态指针,所以你根本没有释放它,事实上这条线certificate了这一点:
printf(“读取%s字符来自%s n%s n”,nChars,cPort,ToHexString(cBuff,nChars)); ^^^^^^^^^^^
你最好这样做:
char * hexedString; hexedString = ToHexString(cBuff,nChars); .... printf(“读取%s字符来自%s n%s n”,nChars,cPort,hexedString); .... 自由(hexedString);
您可以在新数组中返回例程的结果。 使用您的模型,使用结果释放此数组的责任在于调用者。 因此,在调用者中,您应该将例程的结果存储在临时文件中,随意执行任何操作,然后在结束时释放()它。
以上就是c/c++开发分享为什么没有内存泄漏?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/541914.html