VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 607|回复: 16

[已解决]内存泄漏,为啥cstring会造成内存泄漏,这看不明白

[复制链接]
14_avatar_middle
最佳答案
1 
online_vip 发表于 2021-3-22 17:41:19 | 显示全部楼层 |阅读模式

这个函数,这里是开始调用出内存泄漏的地方




void EnumNetCards()
{

        DWORD Status, Problem;
        LPTSTR Buffer = NULL;
        DWORD BufSize = 0;

        // 返回所有设备信息
        HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES);

        if (INVALID_HANDLE_VALUE == hDevInfo)
                return;


        SP_DEVINFO_DATA DeviceInfoData = { sizeof(SP_DEVINFO_DATA) };


        //
        // 枚举设备
        //
        for (DWORD DeviceId = 0;
                SetupDiEnumDeviceInfo(hDevInfo, DeviceId, &DeviceInfoData);
                DeviceId++)
        {

                // 获得设备的状态
                if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst, 0) != CR_SUCCESS)
                        continue;


                // 获取设备类名
                TCHAR szDevName[MAX_PATH] = _T("");
                if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_CLASS, &Buffer, (PULONG)&BufSize))
                {
                        lstrcpyn(szDevName, Buffer, MAX_PATH);
                }


                if (lstrcmp(szDevName, _T("Net")) == 0)
                {
                        TCHAR szName[MAX_PATH] = _T("");
                        if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_ENUMERATOR_NAME, &Buffer, (PULONG)&BufSize))
                        {
                                lstrcpyn(szName, Buffer, MAX_PATH);
                        }


                        if (lstrcmp(szName, _T("ROOT")) != 0)
                        {

                                if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DRIVER, &Buffer, (PULONG)&BufSize))
                                {
                                        lstrcpyn(szName, Buffer, MAX_PATH);

                                         //获取设备描述
                                        if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, &Buffer, (PULONG)&BufSize))
                                        {

                                                lstrcpyn(szName, Buffer, MAX_PATH);


                                                CString str1 = szName;
                                                CString str2 = _T("");
                                                str2 = str1.Mid(0, 11);
                                                if (str2 == "Realtek USB")
                                                {
                                                        if (bRet_server)
                                                        {
                                                                if (ControlDevice(DeviceId, hDevInfo))
                                                                {
                                                                        printf("Successful\n");
                                                                }
                                                                else
                                                                {
                                                                        printf("FAILED\n");
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }

        SetupDiDestroyDeviceInfoList(hDevInfo);
}




这里是内存泄漏的代码块:
CStringData* CAfxStringMgr::Allocate( int nChars, int nCharSize ) throw()
{
        size_t nTotalSize;
        CStringData* pData;
        size_t nDataBytes;

        ASSERT(nCharSize > 0);
       
        if(nChars < 0)
        {
                ASSERT(FALSE);
                return NULL;
        }
       
        nDataBytes = (nChars+1)*nCharSize;
        nTotalSize = sizeof( CStringData )+nDataBytes;
        pData = (CStringData*)malloc( nTotalSize );
        if (pData == NULL)
                return NULL;
        pData->pStringMgr = this;
        pData->nRefs = 1;
        pData->nAllocLength = nChars;
        pData->nDataLength = 0;

        return pData;
}
最佳答案
70_avatar_small
2021-3-23 16:01:11
SyY 发表于 2021-3-23 13:42
我直接放弃用cstring了,把cstring作为全局变量也不行,cstring的free是每次都有进的,具体哪里问题确实 ...

你不是想禁用网卡么,直接com组件多省事。。
https://blog.csdn.net/qq_38777624/article/details/114930369




上一篇:内存泄漏,为什么是cstring的,到底啥原因造成的
下一篇:if else if 不知为何出错
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-22 17:42:20 | 显示全部楼层
CString str1 = szName;                                                 CString str2 = _T("");                                                 str2 = str1.Mid(0, 11);就是这一句,str2这里,发生的内存泄漏,到底是为什么呢?????csrting不是不会内存泄漏吗
70_avatar_middle
最佳答案
47 
在线会员 发表于 2021-3-22 18:57:47 | 显示全部楼层
你的意思是崩溃? 有没有可能str1 小于11
31_avatar_middle
最佳答案
25 
在线会员 发表于 2021-3-22 20:33:20 | 显示全部楼层
成对使用,成对使用,成对使用!
内存:
malloc出来的要free,
new出来的要delete,
文件、各类名柄:
open完了close.
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-23 09:05:11 | 显示全部楼层
tony666 发表于 2021-3-22 18:57
你的意思是崩溃? 有没有可能str1 小于11

不是崩溃,只有检查内存泄漏才会停在这里,我发现,不是str2的问题,因为注释掉这一句也会停在上一句,就是貌似是szname的问题,会不会是tchar和lptstr 和cstring的转换哪里有问题啊?
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-23 09:06:12 | 显示全部楼层
cpp2019 发表于 2021-3-22 20:33
成对使用,成对使用,成对使用!
内存:
malloc出来的要free,

你说的没错,我没有new啊,cstring只是一个对象,但是转换前是一个lptstr的指针,可能这里有问题?
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-23 09:07:30 | 显示全部楼层
tony666 发表于 2021-3-22 18:57
你的意思是崩溃? 有没有可能str1 小于11

                        TCHAR szName[MAX_PATH] = _T("");
                        if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_ENUMERATOR_NAME, &Buffer, (PULONG)&BufSize))
                        {
                                lstrcpyn(szName, Buffer, MAX_PATH);
                        }
是否会是这句有问题?
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-23 09:47:28 | 显示全部楼层
tony666 发表于 2021-3-22 18:57
你的意思是崩溃? 有没有可能str1 小于11

BOOL GetRegistryProperty(HDEVINFO DeviceInfoSet,
        PSP_DEVINFO_DATA DeviceInfoData,
        ULONG Property,
        PVOID Buffer,
        PULONG Length)
{
        while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
                DeviceInfoData,
                Property,
                NULL,
                (BYTE *)*(TCHAR **)Buffer,
                *Length,
                Length))
        {
                // 长度不够则重新分配缓冲区
                if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
                {
                        if (*(LPTSTR *)Buffer)
                                LocalFree(*(LPTSTR *)Buffer);

                        *(LPTSTR *)Buffer = (PCHAR)LocalAlloc(LPTR, *Length);
                }
                else
                {
                        return false;
                }
        }

        return (BOOL)(*(LPTSTR *)Buffer)[0];
}
会不会是我 这个调用的函数 的问题啊
31_avatar_middle
最佳答案
25 
在线会员 发表于 2021-3-23 09:53:04 | 显示全部楼层
SyY 发表于 2021-3-23 09:07
TCHAR szName[MAX_PATH] = _T("");
                        if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_E ...


问题在于有malloc这段代码,你的代码中申请的堆内存用完了并没有释放,你的函数设计有问题!好好学学内存这块的基础!
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-23 10:02:40 | 显示全部楼层
cpp2019 发表于 2021-3-23 09:53
问题在于有malloc这段代码,你的代码中申请的堆内存用完了并没有释放,你的函数设计有问题!好好学学内 ...

   {
                // 长度不够则重新分配缓冲区
                if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
                {
                        if (*(LPTSTR *)Buffer)
                                LocalFree(*(LPTSTR *)Buffer);

                        *(LPTSTR *)Buffer = (PCHAR)LocalAlloc(LPTR, *Length);
                }
                else
                {
                        return false;
                }
        }

你说的是这里有问题?这里是释放了再申请,这有问题吗,每次进来都会释放掉
70_avatar_middle
最佳答案
47 
在线会员 发表于 2021-3-23 12:14:35 | 显示全部楼层
本帖最后由 tony666 于 2021-3-23 12:18 编辑

我只看出来最后退出EnumNetCards 的时候 最后一个buffer没释放。。。
另外请教个问题,你是用啥工具查看内存泄漏的,我从来都是靠眼。。。内存泄漏,为啥cstring会造成内存泄漏,这看不明白
31_avatar_middle
最佳答案
25 
在线会员 发表于 2021-3-23 13:12:55 | 显示全部楼层
8楼的函数也有问题,只有在if满足时才会调用一次free,1楼你自己标明的函数也有问题,变量作用域你没搞懂。
  1. 这里是内存泄漏的代码块:
  2. CStringData* CAfxStringMgr::Allocate( int nChars, int nCharSize ) throw()
  3. {
  4.         size_t nTotalSize;
  5.         CStringData* pData;
  6.         size_t nDataBytes;

  7.         ASSERT(nCharSize > 0);
  8.       
  9.         if(nChars < 0)
  10.         {
  11.                 ASSERT(FALSE);
  12.                 return NULL;
  13.         }
  14.       
  15.         nDataBytes = (nChars+1)*nCharSize;
  16.         nTotalSize = sizeof( CStringData )+nDataBytes;
  17.         pData = (CStringData*)malloc( nTotalSize );
  18.         if (pData == NULL)
  19.                 return NULL;
  20.         pData->pStringMgr = this;
  21.         pData->nRefs = 1;
  22.         pData->nAllocLength = nChars;
  23.         pData->nDataLength = 0;

  24.         return pData;
  25. }
复制代码
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-23 13:41:02 | 显示全部楼层
tony666 发表于 2021-3-23 12:14
我只看出来最后退出EnumNetCards 的时候 最后一个buffer没释放。。。
另外请教个问题,你是用啥工具查看内 ...

我放弃用cstring了 然后就没有内存泄漏了 直接用auto类型
内存泄漏用        //_CrtDumpMemoryLeaks();关键字
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-23 13:42:59 | 显示全部楼层
cpp2019 发表于 2021-3-23 13:12
8楼的函数也有问题,只有在if满足时才会调用一次free,1楼你自己标明的函数也有问题,变量作用域你没搞懂。 ...

我直接放弃用cstring了,把cstring作为全局变量也不行,cstring的free是每次都有进的,具体哪里问题确实找不到,总体就是 tchar和cstring的转换  这里可能有编码的问题,中文的时候会报错
70_avatar_middle
最佳答案
47 
在线会员 发表于 2021-3-23 16:01:11 | 显示全部楼层    本楼为最佳答案   
bestAnswer
SyY 发表于 2021-3-23 13:42
我直接放弃用cstring了,把cstring作为全局变量也不行,cstring的free是每次都有进的,具体哪里问题确实 ...

你不是想禁用网卡么,直接com组件多省事。。
https://blog.csdn.net/qq_38777624/article/details/114930369
70_avatar_middle
最佳答案
47 
在线会员 发表于 2021-3-23 16:02:21 | 显示全部楼层
SyY 发表于 2021-3-23 13:41
我放弃用cstring了 然后就没有内存泄漏了 直接用auto类型
内存泄漏用        //_CrtDumpMemoryLeaks();关键字

学习了,谢谢
14_avatar_middle
最佳答案
1 
ico_lz  楼主| 发表于 2021-3-23 16:41:15 | 显示全部楼层
tony666 发表于 2021-3-23 16:01
你不是想禁用网卡么,直接com组件多省事。。
https://blog.csdn.net/qq_38777624/article/details/11493 ...

确实可以,这个还挺好用,com组件好东西
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号-4 )|网站地图wx_jqr

GMT+8, 2021-8-4 20:37

Powered by CcTry.CoM

© 2009-2021 cctry.com

快速回复 返回顶部 返回列表