从dll调用函数时分配大小无效

Invalid allocation size when calling a function from dll

本文关键字:无效 分配 dll 调用 函数      更新时间:2023-10-16

我刚开始使用dll,但以前没有遇到过这个问题,所以它可能没有连接dll。我有在c++中实现的KMP字符串匹配算法,我使用dll从c#调用它。

这是我的出口:

extern "C" __declspec (dllexport) const char* naive(const char* text, const   char* str);
extern "C" __declspec (dllexport) const char* KMP(const char* text, const char* str);

我的导入:

 [DllImport(@"dll_path", CallingConvention = CallingConvention.Cdecl)]
 public static extern IntPtr KMP([MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string str);

从c#调用

  string output = Marshal.PtrToStringAnsi(KMP(richTextBox1.Text, richTextBox2.Text));

和c++函数:

const char* KMP(const char* text, const char* str)
{
    int tL = strlen(text);
    int sL = strlen(str);
    /* Algorithm */
 }

在调用函数后立即引发异常。所以我认为这不是代码实现。有线的事情是,只有当第二个参数(str)中有一个"\n"新行时,它才会被抛出,无论具体在哪里。如果没有新的线路,它会正常运行。最让我困惑的是,为什么只有第二个论点,两者的声明和使用都是相同的。我也实现了Naive算法,同样的故事。

我发现的所有答案都是只有当一个负数作为数组或未声明变量的大小时,而指针上没有。但我怀疑它是否相似,因为当我的搜索字符串(第二个参数(str))不包含新行时,代码会正常执行。

有什么想法吗?

谢谢你在前面。

EDIT(函数体):

const char* KMP(const char* text, const char* str)
{
    int tL = strlen(text);
    int sL = strlen(str);
    string match = "";
    if (sL == 0 || tL == 0)
        throw "both text and string must be larger than 0";
    else if (sL > tL)
        throw "the text must be longer than the string";
    int tI = 0;
    int col = 0, row = 0;
    while (tI <= tL - sL)
    {
        int i = 0;
        int tmpCol = -1;
        int next = 1;
        for (; i <= sL && text[i + tI] != ''; i++)
        {
            if (text[i + tI] == 'n')
            {
                row++;
                tmpCol++;
            }
            if (text[i + tI] == str[0] && next == 1 && i > 0)
                next = i;
            if (text[i + tI] != str[i])
                break;
        }
        if (i == sL)
        {
            match += to_string(row) + ',' + to_string(col) + ';';
        }
        tI += next;
        col = tmpCol > -1 ? tmpCol : col + next;
    }
    char* c = new char[match.length() - 1];
    c[match.length() - 1] = '';
    for (int i = 0; i < match.length() - 1; i++)
        c[i] = match[i];
    return c;
}

只需更改代码以处理不匹配的情况,因为运行时无法分配0-1 = 0xFFFFFFFFF字节。现在我还更改了您的复制缓冲区分配和循环代码,以避免覆盖(正如@HenkHoltermann所指出的):

...
if (match.length() == 0)
    return "No matches";
// Allocate for all chars +  except the last semicolon
char* c = new char[match.length()];
c[match.length() - 1] = '';
// Copy all chars except the last semicolon
for (int i = 0; i < match.length() - 1; i++)
    c[i] = match[i];
return c;

它仍然没有复制最后一个分号,所以如果您需要它,那么您将不得不在缓冲区中再添加一个符号。


p。S.:我还看到你的代码有一些问题:

  1. 您使用C++异常。虽然CLR会将它们捕获为SEH(因为VC++使用SEH),但总体而言,这仍然不是一个好主意——跨DLL边界抛出C++异常
  2. 长度int tL = strlen(text);使用有符号intstrlen返回无符号size_t。这可能不是一个实际的问题,但也不是一个正确的方式