慎用USES_CONVERSION

本文详细分析了USES_CONVERSION宏在ATL库中的使用方式及其可能导致的内存泄露问题,提供了两种解决方案:一是手动实现字符转换函数以避免内存泄露;二是将转换操作封装到独立函数中,避免在循环体内重复调用导致的栈溢出。通过实例代码解释了问题的根源,并指导开发者如何预防和解决类似问题。
USES_CONVERSION是ATL中的一个宏定义。用于编码转换(用的比较多的是CString向LPCWSTR转换)。在ATL下使用要包含头文件#include "atlconv.h"

使用USES_CONVERSION一定要小心,它们从堆栈上分配内存,直到调用它的函数返回,该内存不会被释放。如果在一个循环中,这个宏被反复调用几万次,将不可避免的产生stackoverflow。

 

在一个函数的循环体中使用A2W等字符转换宏可能引起栈溢出。

#include <atlconv.h>
void fn()
{
    while(true)
    {
        {
            USES_CONVERSION;
            DoSomething(A2W("SomeString"));
        }
    }
}

让我们来分析以上的转换宏

#define A2W(lpa) (\
   ((_lpa = lpa) == NULL) ? NULL : (\
      _convert = (lstrlenA(_lpa)+1),\
      ATLA2WHELPER((LPWSTR) alloca(_convert*2), _lpa, _convert)))

#define ATLA2WHELPER AtlA2WHelper

inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp)
{
   ATLASSERT(lpa != NULL);
   ATLASSERT(lpw != NULL);
   // verify that no illegal character present
   // since lpw was allocated based on the size of lpa
   // don't worry about the number of chars
   lpw[0] = '\0';
   MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);
   return lpw;
}

关键的地方在 alloca  内存分配内存上。
#define alloca  _alloca

_alloca
Allocates memory on the stack.

Remarks
_alloca allocates size bytes from the program stack. The allocated space is automatically freed when the calling function

exits. Therefore, do not pass the pointer value returned by _alloca as an argument to free.

问题就在这里,分配的内存是在函数的栈中分配的。而VC编译器默认的栈内存空间是2M。当在一个函数中循环调用它时就会不断的分配栈中的内存。

以上问题的解决办法:
1、自己写字符转换函数,不要偷懒
Function that safely converts a 'WCHAR' String to 'LPSTR':
char* ConvertLPWSTRToLPSTR (LPWSTR lpwszStrIn)
{
  LPSTR pszOut = NULL;
  if (lpwszStrIn != NULL)
  {
 int nInputStrLen = wcslen (lpwszStrIn);

 // Double NULL Termination
 int nOutputStrLen = WideCharToMultiByte (CP_ACP, 0, lpwszStrIn, nInputStrLen, NULL, 0, 0, 0) + 2;
 pszOut = new char [nOutputStrLen];

 if (pszOut)
 {
   memset (pszOut, 0x00, nOutputStrLen);
   WideCharToMultiByte(CP_ACP, 0, lpwszStrIn, nInputStrLen, pszOut, nOutputStrLen, 0, 0);
 }
  }
  return pszOut;
}
等等一个一个的实现。

2、把字符转换部分放到一个函数中处理。

void fn2()
{
    USES_CONVERSION;
    DoSomething(A2W("SomeString"));
}

void fn()
{
    while(true)
    {
        fn2();
    }
}

如果不知道这点问题,在使用后崩溃时很难查出崩溃原因的。


(pdal-env) D:\scau_lidar_data\output>3d-tiles-tools lasTo3dtiles -i C22.las -o h Usage: 3d-tiles-tools <command> [options] Commands: convert Convert between tilesets and tileset package formats. The input and output can be one of the following: - The path of a tileset JSON file - The path of a directory that contains a 'tileset.json' file - The path of a '.3tz' file - The path of a '.3dtiles' file The input can also be the path of a ZIP file that contains the tileset data. The tileset JSON file in this ZIP is determined by the 'inputTilesetJsonFileName', which is 'tileset.json' by default. glbToB3dm Repackage the input glb as a b3dm with a basic header. glbToI3dm Repackage the input glb as a i3dm with a basic header. b3dmToGlb Extract the binary glTF asset from the input b3dm. i3dmToGlb Extract the binary glTF asset from the input i3dm. cmptToGlb Extract the binary glTF assets from the input cmpt. splitCmpt Split the input cmpt and write out its inner tiles. convertB3dmToGlb Convert a b3dm file into a glTF asset that uses glTF extensions to represent the batch- and feature table information convertPntsToGlb Convert a pnts file into a glTF asset that uses glTF extensions to represent the point properties and batch- and feature table information convertI3dmToGlb Convert an i3dm file into a glTF asset that uses glTF extensions to represent the batch- and feature table information. This conversion may be lossy if the GLB of the input i3dm contains animations. optimizeB3dm Pass the input b3dm through gltf-pipeline. To pass options to gltf-pipeline, place them after --options. (--options -h for gltf-pipeline help) optimizeI3dm Pass the input i3dm through gltf-pipeline. To pass options to gltf-pipeline, place them after --options. (--options -h for gltf-pipeline help) updateAlignment Update the alignment of the batch- and feature table and the tile dataas a whole, to meet the alignment requirements of the specification. This can be applied to B3DM, I3DM, PNTS, or CMPT tile data. gzip Gzips the input tileset directory. ungzip Ungzips the input tileset directory. combine Combines all external tilesets into a single tileset.json file. merge Merge any number of tilesets together into a single tileset. mergeJson Merge any number of tilesets together into a single tileset without copying resources to output directory. upgrade Upgrades legacy tilesets to comply to the 3D Tiles specification. By default, this will upgrade legacy tilesets to comply to 3D Tiles 1.0. These upgrades include: - The asset version will be set to '1.0' - Content that uses a 'url' will be upgraded to use 'uri'. - The 'refine' value will be converted to be in all-uppercase. - glTF 1.0 models in B3DM or I3DM will be upgraded to glTF 2.0. When specifying '--targetVersion 1.1', then the upgrades will include: - The asset version will be set to '1.1' - Content that uses a 'url' will be upgraded to use 'uri'. - The 'refine' value will be converted to be in all-uppercase. - The '3DTILES_content_gltf' extension declaration will be removed. - PNTS, B3DM, and I3DM content will be converted to glTF. pipeline Execute a pipeline that is provided as a JSON file analyze Analyze the input file, and write the results to the output directory. This will accept B3DM, I3DM, PNTS, CMPT, and GLB files (both for glTF 1.0 and for glTF 2.0), and write files into the output directory that contain the feature table, batch table, layout information, the GLB, and the JSON of the GLB tilesetToDatabase Create a sqlite database for a tileset. (Deprecated - use 'convert' instead) databaseToTileset Unpack a tileset database to a tileset folder. (Deprecated - use 'convert' instead) createTilesetJson Creates a tileset JSON file that just refers to given tile content files. If the input is a single file, then this will result in a single (root) tile with the input file as its tile content. If the input is a directory, then all content files in this directory will be used as tile content, recursively. The exact set of file types that are considered to be 'tile content' is not specified, but it will include GLB, B3DM, PNTS, I3DM, and CMPT files. Options: --version Show version number [boolean] -h, --help Show help [boolean] -f, --force Output can be overwritten if it already exists. [boolean] [default: false] --logLevel The log level. Valid values are 'trace', 'debug', 'info', 'warn', 'error', 'fatal', and 'silent' [string] [default: "info"] --logJson Whether log messages should be printed as JSON instead of pretty-printing [boolean] [default: false] Unknown arguments: i, o, lasTo3dtiles
最新发布
10-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值