在CLI中处理String ^?

时间:2009-08-13 14:59:28

标签: string memory-leaks c++-cli

我的代码中有关于CLI / C ++中的字符串的小内存泄漏。我试图通过删除我的unsigned char数组来修复泄漏,但是当我这样做时,我得到了一个内存访问冲突。

我认为这是因为System :: String是一个ref类型,因此,内存在下面的代码中与'testString'和'uch'相关联。那是对的吗?如果是这样,我如何分离内存,以便我可以释放内存并仍然返回一个System :: String?

myStatus get_testString(String^% testString)
{
    uchar* uch = 0;
    bool b = MgdStringToUChar(testString, uch);
    myStatus s = m_NativeMsg->get_testString(uch);
    testString = (reinterpret_cast<const char*>(uch));

    delete []uch;//this line causes an error       
    uch=0; 
    return s;
}

static bool MgdStringToUChar(System::String^ s, uchar*& uch)
{
    pin_ptr<const wchar_t> wch = PtrToStringChars( s ); 
    int len = (( s->Length+1) * 2); 
    size_t * st = 0; 
    char *ch = new char[ len ]; 
    bool result = wcstombs_s(st,ch, len, wch, len ) != -1; 
    if(!result) 
        throw (gcnew Exception("Could not parse string in :: MgdStringToUChar")); 
    uch = new uchar[len]; 
    int i=0; 
    while(i<len+1) 
    { 
        uch[i] = ch[i]; 
        i++; 
    } 
    delete st; 
    st=0; 
    delete [] ch; 
    ch=0; 
    return true; 
}; 

1 个答案:

答案 0 :(得分:1)

好的,首先你的MgdStringToUChar函数存在一些问题。 wcstombs_s的第一个参数应该是指向实际size_t的指针,而不是指向null的指针。如果你想确保ch被终止,那么你也应该使用_TRUNCATE或len-1作为计数参数。

从ch缓冲区到生成的uchar缓冲区的副本也可能会超过缓冲区的末尾。

static bool MgdStringToUChar(System::String^ s, uchar*& uch)
{
    pin_ptr<const wchar_t> wch = PtrToStringChars( s ); 
    int len = (( s->Length+1) * 2); 
    size_t st = 0;
    char *ch = new char[ len ]; 

    bool result = wcstombs_s(&st, ch, len, wch, _TRUNCATE) != -1; 
    if(!result) 
        throw (gcnew Exception("Could not parse string in :: MgdStringToUChar")); 

    uch = new uchar[st+1]; 
    uch[st] = NULL;

    for(int i = 0; i < st; i++) 
    { 
        uch[i] = ch[i]; 
    } 

    delete [] ch; 

    return true; 
}; 

考虑到您似乎需要基本的ANSI转换,您也可以更简单地执行此操作:

static bool MgdStringToUChar(System::String^ s, uchar*& uch)
{
    char* ch = (char*)(void*)Marshal::StringToHGlobalAnsi(str);

    size_t st = strlen(ch);
    uch = new uchar[st + 1]; 
    uch[st] = NULL;

    for(int i = 0; i < st; i++) 
    { 
        uch[i] = ch[i]; 
    } 

    Marshal::FreeHGlobal(ch);

    return true; 
}; 

这应该会好一点。但是我仍然担心get_testString对uch中的数据做了什么。没有看到全貌,很难看出这里发生了什么。