Visual c++ std::wstring导致内存访问冲突(0xC0000005:访问冲突)

Visual c++ std::wstring导致内存访问冲突(0xC0000005:访问冲突),visual-c++,memory,activex,named-pipes,Visual C++,Memory,Activex,Named Pipes,我们的应用程序在命名管道列表中导航,并查找由应用程序创建的命名管道 如果命名管道不存在,我们将继续创建一个。然而,最近我们的客户报告 应用程序在第行崩溃: fileName = std::wstring(TmpInfo->FileName); 您可以查看下面随附的windbg崩溃转储报告。这次事故是偶发的,并非总是可以重现的。你能帮我确定这个问题吗?将TmpInfo->FileName转换为wstring时是否存在问题。请注意,此组件是一个ActiveX控件。我们的ActiveX正在使其

我们的应用程序在命名管道列表中导航,并查找由应用程序创建的命名管道

如果命名管道不存在,我们将继续创建一个。然而,最近我们的客户报告

应用程序在第行崩溃:

fileName = std::wstring(TmpInfo->FileName);
您可以查看下面随附的windbg崩溃转储报告。这次事故是偶发的,并非总是可以重现的。你能帮我确定这个问题吗?将
TmpInfo->FileName
转换为
wstring
时是否存在问题。请注意,此组件是一个ActiveX控件。我们的ActiveX正在使其他应用程序崩溃

下面的代码负责枚举命名管道

typedef struct {
        ULONG                   NextEntryOffset;
        ULONG                   FileIndex;
        ULONG                   FileNameLength;
        WCHAR                   FileName[1];    
    } FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;


inline void EnumerateRunningPipes(std::vector<std::wstring>& pipeNames, std::wstring stringLookup,      

                                     bool useStringLookup, bool 

truncatePipeDirPrefix)
    {
        LONG ntStatus;   
        IO_STATUS_BLOCK IoStatus;       
        BOOL bReset = TRUE;       
        PFILE_NAMES_INFORMATION fileNameInfo, TmpInfo;              

        fileNameInfo = (PFILE_NAMES_INFORMATION) new BYTE[1024];

        HANDLE hPipe = CreateFile("//./pipe/", 
            GENERIC_READ,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);

        if(hPipe == INVALID_HANDLE_VALUE)
            throw CEnumeratePipeException("Could not get handle to root directory for pipes.",
            CEnumeratePipeException::ErrorType::CREATE_FILE, GetLastError());       

        USES_CONVERSION;

        locale loc;
        mbstate_t state = {0};

        while(true)
        {
            memset(fileNameInfo, 0, 1024);
            ntStatus = NtQueryDirectoryFile( hPipe, NULL, NULL, NULL, &IoStatus, fileNameInfo, 

1024,
                FileNameInformation, FALSE, NULL, bReset );

            if (ntStatus!=NO_ERROR)   
            {   
                if (ntStatus == STATUS_NO_MORE_FILES)                       


                    break;              

                std::stringstream sstream;      
                sstream << "NtQueryDirectoryFile error " << ntStatus;

                logger->writeLog(sstream.str()); 
                throw CEnumeratePipeException(
                    "NtQueryDirectoryFile could not get information about the directory or 

file.", 
                    CEnumeratePipeException::ErrorType::QUERY_DIR, ntStatus);
            }   

            TmpInfo = fileNameInfo;                         

            while(true)   
            {           
                const int endStringAt = TmpInfo->FileNameLength / sizeof(WCHAR);        



                std::wstring fileName;

                try
                {                                       
                    fileName = std::wstring(TmpInfo->FileName);//The access violation 

occurs at this line of code.
                    fileName = fileName.substr(0, endStringAt);
                }
                catch (...)
                {
                    logger->writeLog("Caught unknown exception.");

                    if (TmpInfo->FileName == NULL)
                    {
                        logger->writeLog("TmpInfo->FileName = NULL");           


                    }                   
                }

                if (useStringLookup)
                {               
                    if (fileName.find(stringLookup) != std::wstring::npos)
                    {       
                        if (!truncatePipeDirPrefix)
                            fileName.insert(0, L"\\\\.\\pipe\\");
                        pipeNames.push_back(fileName);  
                    }   
                }
                else
                {
                    pipeNames.push_back(fileName);
                }

                if(TmpInfo->NextEntryOffset==0)
                    break;   

                TmpInfo = (PFILE_NAMES_INFORMATION)((DWORD)TmpInfo+TmpInfo->NextEntryOffset);
            }   

            bReset = FALSE;
        }   

        delete fileNameInfo;
    }
typedef结构{
ULONG NextEntryOffset;
乌龙文件索引;
ULONG文件名长度;
WCHAR文件名[1];
}文件名信息,*文件名信息;
内联void枚举运行管道(std::vector&pipeNames,std::wstring stringLookup,
bool useStringLookup,bool
截断(EDIRPREFIX)
{
长期状态;
IO_状态_块IoStatus;
BOOL-bReset=TRUE;
PFILE_NAMES_信息fileNameInfo,TmpInfo;
fileNameInfo=(PFILE_NAMES_INFORMATION)新字节[1024];
HANDLE hPipe=CreateFile(“//./pipe/”,
泛读,
文件共享读取文件共享写入文件共享删除,
无效的
开放式,
0,
无效);
if(hPipe==无效的句柄值)
抛出CEnumeratePipeException(“无法获取管道根目录的句柄。”,
CEnumeratePipeException::ErrorType::创建_文件,GetLastError());
使用_转换;
地点loc;
mbstate_t state={0};
while(true)
{
memset(fileNameInfo,0,1024);
ntStatus=NtQueryDirectoryFile(hPipe、NULL、NULL、NULL和IoStatus、fileNameInfo、,
1024,
FileNameInformation,FALSE,NULL,bReset);
如果(ntStatus!=无错误)
{   
如果(ntStatus==状态\u无\u更多\u文件)
打破
std::stringstream和ssstream;
sstream文件名长度/sizeof(WCHAR);
std::wstring文件名;
尝试
{                                       
fileName=std::wstring(TmpInfo->fileName);//访问冲突
在这一行代码处发生。
fileName=fileName.substr(0,endStringAt);
}
捕获(…)
{
logger->writeLog(“捕获未知异常”);
如果(TmpInfo->FileName==NULL)
{
记录器->写日志(“TmpInfo->文件名=NULL”);
}                   
}
如果(使用StringLookup)
{               
if(fileName.find(stringLookup)!=std::wstring::npos)
{       
如果(!截断ePrefix)
文件名。插入(0,L“\\.\\pipe\”;
pipeNames.push_back(文件名);
}   
}
其他的
{
pipeNames.push_back(文件名);
}
如果(TmpInfo->NextEntryOffset==0)
打破
TmpInfo=(文件名信息)((DWORD)TmpInfo+TmpInfo->NextEntryOffset);
}   
bReset=FALSE;
}   
删除fileNameInfo;
}
以下是崩溃转储报告的一部分:

FAULTING_IP: msvcr100!memcpy+57 [f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\memcpy.asm @ 185] 78aa1ed7 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 78aa1ed7 (msvcr100!memcpy+0x00000057) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 00000000 Parameter[1]: 0d6b8000 Attempt to read from address 0d6b8000 SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: msvcr100!memcpy+57 FOLLOWUP_NAME: MachineOwner MODULE_NAME: msvcr100 IMAGE_NAME: msvcr100.dll DEBUG_FLR_IMAGE_TIMESTAMP: 4ba1dbbe FAILURE_BUCKET_ID: STRING_DEREFERENCE_c0000005_msvcr100.dll!memcpy BUCKET_ID: APPLICATION_FAULT_STRING_DEREFERENCE_CODE_ADDRESS_MISMATCH_INVALID_POINTER_READ_WRONG_SYMBOLS_msvcr100!memcpy +57 断层IP: msvcr100!memcpy+57[f:\dd\vctools\crt\u bld\SELF\u X86\crt\src\INTEL\memcpy.asm@185] 78aa1ed7 f3a5代表移动dword ptr es:[edi],dword ptr[esi] 异常记录:ffffffff--(.exr 0xffffffffffffffff) 例外地址:78aa1ed7(msvcr100!memcpy+0x00000057) 例外代码:c0000005(访问冲突) 例外标志:00000000 数字参数:2 参数[0]:00000000 参数[1]:0d6b8000 尝试读取地址0d6b8000 符号\u堆栈\u索引:0 符号名称:msvcr100!memcpy+57 跟进名称:机器所有者 模块名称:msvcr100 图像名称:msvcr100.dll 调试\u FLR\u映像\u时间戳:4ba1dbbe 失败\u BUCKET\u ID:STRING\u DEREFERENCE\u c000005\u msvcr100.dll!memcpy BUCKET\u ID: 应用程序\u故障\u字符串\u解除引用\u代码\u地址\u不匹配\u无效\u指针\u读取错误\u符号\u msvcr100!memcpy +57
如何定义TmpInfo和TmpInfo->FileName?当TmpInfo->FileName崩溃时,您有它的示例值吗


我的猜测是,在某些情况下,它不会以null结尾,导致
std::wstring
的构造函数读入不属于它的内存。

TmpInfo和TmpInfo->FileName是如何定义的?当TmpInfo->FileName崩溃时,您有它的示例值吗


我的猜测是,在某些情况下,它没有以null结尾,导致
std::wstring
的构造函数读入不属于它的内存。

我在文档中没有看到任何说明
文件名
成员以null结尾的内容。并且
FileNameLength
成员的存在表明它不是以null结尾的

所以看起来很可能

fileName = std::wstring(TmpInfo->FileName);
正在读取
TmpInfo
缓冲区的结尾,直到它遇到两个连续的空字节。如果在空字节到达不可读的虚拟内存区域之前没有遇到空字节,则会出现访问冲突

我建议替换这两行代码:

fileName = std::wstring(TmpInfo->FileName);
fileName = fileName.substr(0, endStringAt);
为此:

fileName = std::wstring(TmpInfo->FileName, TmpInfo->FileNameLength);
该构造函数将只从缓冲区中读取
FileNameLength
字符,因此它不应该