关闭时应用程序崩溃 - 使用混合模式DLL

时间:2015-02-25 16:23:56

标签: c++-cli interop boost-asio unmanaged managed

程序关闭时,我的应用程序崩溃了。否则运行正常 设置:
- Visual Studio 2012(x64 Windows 7)
- 混合C ++ / CLI与本机代码DLL(本机代码是Boost Asio)
- 与DLL链接的CLR控制台应用程序

当我“调试”崩溃相关消息时:

  

未处理的异常... 0xC0020001:字符串绑定无效

我发现这个描述错误的MS模糊:crashes with 0xc0020001
总结一下,当托管代码与非托管代码混合不当时会发生这种情况。 但是我无法确定我的代码混合不正确的位置。

文件“UnmanagedBoostStuff.cpp”的属性设置为 No Common Language RunTime Support

我读到了当你包含一个包含本机代码的标题来包围include语句时:

// #pragma unmanaged
// push managed state on to stack and set unmanaged state
#pragma managed(push, off)
#include "UnmanagedBoostStuff.h"
// #pragma managed
#pragma managed(pop)

DLL文件'MixedClrDLL.h'

// MixedClrDLL.h

#pragma once

/* 
 *
 * Add the following preprocessor definitions:
 *   BOOST_ALL_DYN_LINK
 *   _WIN32_WINNT=0x0501
 *
 * Turn off Precompiled Headers
 *
 * Make sure CLR is turned off for native code.
 */   

// #pragma unmanaged
// push managed state on to stack and set unmanaged state
#pragma managed(push, off)
#include "UnmanagedBoostStuff.h"
// #pragma managed
#pragma managed(pop)

using namespace System;
using namespace System::Runtime::InteropServices;

namespace MixedClrDLL {

    public ref class SerialPort
    {
        BlockingReader *nativeClassPtr;
    public:
        SerialPort(System::String ^portName, int timeoutMillis);

        ~SerialPort() 
        { 
            if (m_isDisposed)
            {
                return;
            }
            Diagnostics::Trace::WriteLine("destructor of SerialPort class");
            this->!SerialPort(); 
            m_isDisposed = true;
        }

        !SerialPort() 
        {
            Diagnostics::Trace::WriteLine("destruct-Finalizer of SerialPort class");
            delete nativeClassPtr;
            nativeClassPtr = nullptr;
        }

    private:
        bool m_isDisposed;
    };
}

DLL文件'MixedClrDLL.cpp'

// This is the main DLL file.

#include "stdafx.h"

#include "MixedClrDLL.h"

#include <iostream>

using namespace MixedClrDLL;
using namespace System;

SerialPort::SerialPort(System::String ^portName, int timeoutMillis)
{   
    // Marshal the managed string to unmanaged memory. 
    char* stringPointer = (char*) Marshal::StringToHGlobalAnsi(portName).ToPointer();

    try
    {   
        nativeClassPtr = new BlockingReader(stringPointer, timeoutMillis);
    }

    catch ( Runtime::InteropServices::SEHException^ ) 
    {
      std::cout<< "caught an SEH Exception in SerialPort constructor" << std::endl;
      nativeClassPtr = nullptr;
      throw("Invalid com-port name");
    }

    Console::WriteLine("Execution continuing in SerialPort constructor: ");

    // Always free the unmanaged string.
    Marshal::FreeHGlobal(IntPtr(stringPointer));
}

DLL文件'UnmanagedBoostStuff.h'

#pragma once

#include <boost/asio.hpp>

class BlockingReader
{

public: 
    BlockingReader(const char *name, size_t timeout);
    ~BlockingReader();

private:    
    boost::asio::io_service io;
    boost::asio::serial_port port;
    size_t timeout; 
    boost::asio::deadline_timer timer;
    bool read_error;
};

DLL文件'UnmanagedBoostStuff.cpp'

#include "stdafx.h"

#include "UnmanagedBoostStuff.h"

#include <boost/bind.hpp>
#include <iostream>

/*
 * Set "No Common Language RunTime Support" for the 
 * properties of this cpp file.
 *
 */
BlockingReader::BlockingReader(const char *name, size_t timeout) :
    io(), port(io, name), timeout(timeout),
                                timer(io),
                                read_error(true)
{
    std::cout<< "in Blocking Reader constructor: " << name << std::endl;
    port.set_option(boost::asio::serial_port_base::baud_rate(115200));
}

BlockingReader::~BlockingReader()
{
    std::cout<< "in Blocking Reader DE-structor" << std::endl;
    if (port.is_open())
    {
        std::cout<< " port is open - closing it" << std::endl;
        port.close();
        //Sleep(100);
        if (port.is_open())
        {
            std::cout<< "Port is STILL open" << std::endl;
        }
        else
        {
            std::cout<< "Port is now Closed" << std::endl;
        }
    }
    else
    {
        std::cout<< "Port wasn't open open" << std::endl;
    }
}

最后是CLR控制台应用程序文件'ClrConsoleApp.cpp'

// ClrConsoleApp.cpp : main project file.

#include "stdafx.h"
#include <iostream>

using namespace System;
using namespace MixedClrDLL;

void localTest();

int main(array<System::String ^> ^args)
{
    Console::WriteLine(L"Testing Mixed-Managed/Native");
    localTest();

    char ch;
    std::cout << "enter a char to finish" << std::endl;
    std::cin >> ch;
    std::cout << "exiting" << std::endl;
    return 0;
}

void localTest()
{
    std::cout << "in function" << std::endl;
    SerialPort mixedClass("COM1", 500);
    std::cout << "leaving function" << std::endl;
}

感谢您的时间。

procdump输出

>procdump -g -ma -e -x C:\temp\StackOverflow\mixedTest\dumps C:\temp\StackOverflow\mixedTest\ClrConsoleApp\x64\Debug\ClrConsoleApp.exe

ProcDump v7.1 - Writes process dump files
Copyright (C) 2009-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
With contributions from Andrew Richards

Process:               ClrConsoleApp.exe (5428)
CPU threshold:         n/a
Performance counter:   n/a
Commit threshold:      n/a
Threshold seconds:     10
Hung window check:     Disabled
Log debug strings:     Disabled
Exception monitor:     Unhandled
Exception filter:      *
Terminate monitor:     Disabled
Cloning type:          Disabled
Concurrent limit:      n/a
Avoid outage:          n/a
Number of dumps:       1
Dump folder:           C:\temp\StackOverflow\mixedTest\dumps\
Dump filename/mask:    PROCESSNAME_YYMMDD_HHMMSS


Press Ctrl-C to end monitoring without terminating the process.

[12:03:31] Exception: 04242420
Testing Mixed-Managed/Native
in function
in Blocking Reader constructor: COM1
Execution continuing in SerialPort constructor:
leaving function
in Blocking Reader DE-structor
 port is open - closing it
Port is now Closed
enter a char to finish
s
exiting
[12:03:39] Exception: C0020001
[12:03:39] Unhandled: C0020001
[12:03:39] Dump 1 initiated: C:\temp\StackOverflow\mixedTest\dumps\ClrConsoleApp.exe_150227_120339.dmp
[12:03:39] Dump 1 writing: Estimated dump file size is 93 MB.
[12:03:40] Dump 1 complete: 93 MB written in 1.0 seconds
[12:03:40] Dump count reached.

WinDbg分析

Microsoft (R) Windows Debugger Version 6.3.9600.17298 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

Loading Dump File [C:\temp\StackOverflow\mixedTest\dumps\ClrConsoleApp.exe_150227_120339.dmp]
User Mini Dump File with Full Memory: Only application data is available

Comment: '
*** procdump  -g -ma -e -x C:\temp\StackOverflow\mixedTest\dumps C:\temp\StackOverflow\mixedTest\ClrConsoleApp\x64\Debug\ClrConsoleApp.exe
*** Unhandled exception: C0020001'

************* Symbol Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       SRV*C:\temp\SymbolsCache*http://msdl.microsoft.com/download/symbols
Symbol search path is: SRV*C:\temp\SymbolsCache*http://msdl.microsoft.com/download/symbols
Executable search path is: 
Windows 7 Version 7601 (Service Pack 1) MP (4 procs) Free x64
Product: WinNt, suite: SingleUserTS
Machine Name:
Debug session time: Fri Feb 27 12:03:39.000 2015 (UTC - 5:00)
System Uptime: 0 days 1:39:14.776
Process Uptime: 0 days 0:00:08.000
....................................
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(1534.12fc): Unknown exception - code c0020001 (first/second chance not available)
KERNELBASE!RaiseException+0x39:
000007fe`fdd2940d 4881c4c8000000  add     rsp,0C8h
0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

*** WARNING: Unable to verify checksum for MixedClrDLL.dll
*** WARNING: Unable to verify checksum for mscorlib.ni.dll
*** WARNING: Unable to verify checksum for ClrConsoleApp.exe

FAULTING_IP: 
KERNELBASE!RaiseException+39
000007fe`fdd2940d 4881c4c8000000  add     rsp,0C8h

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 000007fefdd2940d (KERNELBASE!RaiseException+0x0000000000000039)
   ExceptionCode: c0020001
  ExceptionFlags: 00000001
NumberParameters: 1
   Parameter[0]: ffffffff8007042b

CONTEXT:  0000000000000000 -- (.cxr 0x0;r)
rax=000000007799fe68 rbx=000007feec660000 rcx=000000000016ea20
rdx=00000000000000c8 rsi=0000000000000000 rdi=000007fe957797f0
rip=000007fefdd2940d rsp=000000000016f030 rbp=000000000016f350
 r8=0000000000000000  r9=0000000000000000 r10=000007fe957797f0
r11=000000000016f070 r12=0000000000000001 r13=0000000000000001
r14=000007feec660000 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000200
KERNELBASE!RaiseException+0x39:
000007fe`fdd2940d 4881c4c8000000  add     rsp,0C8h

DEFAULT_BUCKET_ID:  WRONG_SYMBOLS

PROCESS_NAME:  ClrConsoleApp.exe

ERROR_CODE: (NTSTATUS) 0xc0020001 - The string binding is invalid.

EXCEPTION_CODE: (NTSTATUS) 0xc0020001 - The string binding is invalid.

EXCEPTION_PARAMETER1:  ffffffff8007042b

NTGLOBALFLAG:  70

APPLICATION_VERIFIER_FLAGS:  0

APP:  clrconsoleapp.exe

ANALYSIS_VERSION: 6.3.9600.17298 (debuggers(dbg).141024-1500) amd64fre

MANAGED_STACK: !dumpstack -EE
OS Thread Id: 0x12fc (0)
Current frame: 
Child-SP         RetAddr          Caller, Callee

PRIMARY_PROBLEM_CLASS:  WRONG_SYMBOLS

BUGCHECK_STR:  APPLICATION_FAULT_WRONG_SYMBOLS

LAST_CONTROL_TRANSFER:  from 000007fef51e8194 to 000007fefdd2940d

STACK_TEXT:  
: KERNELBASE!RaiseException+0x39
: clr!COMPlusThrowBoot+0x24
: clr!TheUMEntryPrestubWorker+0x2e
: clr!TheUMEntryPrestub+0x3e
: MixedClrDLL!_CRT_INIT+0x2df
: MixedClrDLL!__DllMainCRTStartup+0x11f
: MixedClrDLL!_DllMainCRTStartup+0x31
: mscoreei!CorDllMain+0x1e5
: mscoree!ShellShim__CorDllMain+0xe1
: mscoree!CorDllMain_Exported+0x37
: ntdll!LdrShutdownProcess+0x1db
: ntdll!RtlExitUserProcess+0x90
: mscoreei!RuntimeDesc::ShutdownAllActiveRuntimes+0x27b
: mscoreei!CLRRuntimeHostInternalImpl::ShutdownAllRuntimesThenExit+0x14
: clr!EEPolicy::ExitProcessViaShim+0x6d
: clr!SafeExitProcess+0x9d
: clr!HandleExitProcessHelper+0x3e
: clr!_CorExeMainInternal+0xf9
: clr!CorExeMain+0x14
: mscoreei!CorExeMain+0xe0
: mscoree!CorExeMain_Exported+0x57
: kernel32!BaseThreadInitThunk+0xd
: ntdll!RtlUserThreadStart+0x1d

STACK_COMMAND:  ~0s; .ecxr ; kb

FOLLOWUP_IP: 
clr!TheUMEntryPrestubWorker+2e
000007fe`f529ff3d e8de13acff      call    clr!GetThread (000007fe`f4d61320)

SYMBOL_STACK_INDEX:  2

SYMBOL_NAME:  clr!TheUMEntryPrestubWorker+2e

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: clr

IMAGE_NAME:  clr.dll

DEBUG_FLR_IMAGE_TIMESTAMP:  5348a1ef

FAILURE_BUCKET_ID:  WRONG_SYMBOLS_c0020001_clr.dll!TheUMEntryPrestubWorker

BUCKET_ID:  X64_APPLICATION_FAULT_WRONG_SYMBOLS_clr!TheUMEntryPrestubWorker+2e

ANALYSIS_SOURCE:  UM

FAILURE_ID_HASH_STRING:  um:wrong_symbols_c0020001_clr.dll!theumentryprestubworker

FAILURE_ID_HASH:  {44cb5842-609a-8fdb-42fb-cf958ade10f6}

Followup: MachineOwner
---------

1 个答案:

答案 0 :(得分:-1)

答案在另一个论坛上由“Viorel_”提供。 这基本上是所有代码managed。取出我列出的pragma并将选项放回原始模块上的/clr。 这在退出时停止了应用程序崩溃。