在本机代码中抛出C ++ / CLI System.NullReferenceException

时间:2016-07-19 00:34:19

标签: c++ c++-cli

我正在研究本机C ++应用程序,我正在尝试利用来自单独程序集的一些托管类来读取/写入最初在C#中开发的数据容器。互操作层基本上是加载数据,然后将托管数据镜像到功能相当的本机数据容器中供应用程序使用(然后显然又回来写入)。

说实话,尝试这种互操作并不是非常有趣,但它主要是在这一点上工作。尽管如此,翻译的一个步骤仍然存在,并且在调试时,托管异常(System.NullReferenceException)仅在本机C ++的行上抛出。我完全不明白为什么会发生这种情况,我希望有人能够了解正在发生的事情。我甚至没想到它会在它投掷的位置处于堆栈的管理部分......

这是我们的代码所做的精简版:

//  The native data types.
class cUnmanagedInterpolator
{
    virtual std::vector<std::pair<double, cUnmanagedInterpolator>& GetPoints() { return mPoints; }
    std::vector<std::pair<double, cUnmanagedInterpolator> mPoints;
};

class cUnmanagedInterpolator_Const : public cUnmanagedInterpolator
{
    virtual double GetValue() const { return mValue; }
    double mValue
};

//  The managed data types (please forgive syntax errors here; they're actually written in C# in our software, and this is just to get the point across).
class ManagedInterpolator
{
    property List<KeyValuePair<double, ManagedInterpolator^>^ Points = gcnew List<KeyValuePair<double, ManagedInterpolator^>();
};

class ManagedInterpolator_Const : public ManagedInterpolator
{
    property double DependentValue;
};

//  The function to mirror the managed data container into a native counterpart.
void CopyManagedPoints( ManagedInterpolator^ rhManagedInterpolator, cUnmanagedInterpolator* pUnmanagedInterpolator )
{
    //  Go through each managed point in the interpolator and add a corresponding unmanaged one.
    for each( auto point in rhManagedContainer->Points )
    {
        //  If this is a constant interpolator, just copy the values.
        if( dynamic_cast<ManagedInterpolator_Const^>( point->Value ) != nullptr )
        {
            //  Create a new unmanaged copy of the point.
            //  I even tried making x and r pointers and allocating the doubles on the heap with "new" to make sure they weren't somehow ending up as CLI types, but it didn't make a difference.
            double x = point->Key;
            double r = dynamic_cast<ManagedInterpolator_Const^>( point->Value )->DependentValue;
            std::pair<double, cUnmanagedInterpolator> newPoint( x, cUnmanagedInterpolator_Const( r ) );

            //  The unmanaged point data was looking weird, and this appeared to be where it was happening, so create a message with what it thinks the point is at this point.
            //  ***The next line is where the System.NullReferenceException is thrown.***
            std::string debugMessage = MakeString( newPoint.first ) + ", " + MakeString( dynamic_cast<cUnmanagedInterpolator_Const*>( &( newPoint.second ) )->GetValue() );

            //  Add the copy to the unmanaged interpolator.
            pUnmanagedInterpolator->GetPoints().push_back( newPoint );

            //  ***Trying to reference the newly created point by using pUnmanagedInterpolator->GetPoints().back() also results in an exception.

            //  Show the debug message to the user.
            AfxMessageBox( debugMessage.c_str() );
        }
        //  Otherwise, add a new base class interpolator.
        else
        {
            cUnmanagedInterpolator* pNewInterp = new cUnmanagedInterpolator();

            //  Recurse as deep as it goes.
            if( pNewInterp )
            {
                pUnmanagedInterpolator->GetPoints().push_back( std::make_pair( point->Key, std::move( *pNewInterp ) ) );
                CopyManagedPoints( point->Value, &( pUnmanagedInterpolator->GetPoints().back().second ) );
                delete pNewInterp;
                pNewInterp = nullptr;
            }
        }
    }
}

//  Roughly how the function would be used.
int main()
{
    ManagedInterpolator^ rhManagedInterpolator = gcnew ManagedInterpolator( /*initialization information*/ );

    cUnmanagedInterpolator* pNewInterp = new cUnmanagedInterpolator();

    CopyManagedPoints( rhManagedInterpolator, pNewInterp );

    //  Use the data...

    return 0;
}

内部if语句中发生异常(前面有三个星号(“***”)的注释标记出现问题的位置)。

如果代码不够清晰,请快速摘要代码:

基本上,数据容器是一个“插值器”,它包含独立和相关值对(“点”)。从属值可以是另一个插值器或标量值。作为插值器的相关值可以根据需要进行深度递归,但必须以固定值结束,该值是从插值器派生的类。

1 个答案:

答案 0 :(得分:1)

您正在使用句柄(^),因此这不是本机代码。问题是您的对newPointcUnmanagedInterpolator个对象作为其第二个值,您尝试dynamic_cast到生成{{1}的行上的cUnmanagedInterpolator_Const }。此强制转换将失败并返回NullReferenceException,当取消引用时将导致异常。

从根本上说,当您使用nullptr时,当您创建该对时,它会切片cUnmanagedInterpolator_Const,并将其身份标记为cUnmanagedInterpolator并且成为cUnmanagedInterpolator_Const