簡體   English   中英

在C#中調試DLLImport

[英]Debugging DLLImport in C#

在過去的12個小時左右的時間里,我一直在嘗試讓MySQL嵌入式庫在我的C#應用​​程序中運行,並且已經停滯了很長時間。 調用mysql_server_init()時出現以下錯誤...

未處理的異常:System.AcessViolationException:嘗試讀取或寫入受保護的內存。

C ++方法采用一個int和兩個char**作為參數,但是有人告訴我,以空終止的string[]數組在C#中就足夠了。 由於這是您應該調用的第一種方法,因此我對此問題有些茫然。

這是我的代碼......

public class MySQLServer
{
    [DllImport("libmysqld.dll")]
    static extern int mysql_server_init(int argc, string[] argv, string[] groups);

    [DllImport("libmysqld.dll")]
    static extern void mysql_server_end();

    public static bool Start()
    {
        string[] argv = new string[3];
        argv[0] = "mysql_test";
        argv[1] = "--datadir=C:/MYSQLTEST";
        argv[2] = null;

        string[] groups = new string[3];
        groups[0] = "libmysqd_server";
        groups[1] = "libmysqd_client";
        groups[2] = null;

        int res;

        if ((res = mysql_server_init(3, argv, groups)) == 1)
        {
            Console.WriteLine("MySQL Library Init Failed with error code: %d", res);
            return false;
        }

        Console.WriteLine("MySQL Library Started Successfully!");
        return true;
    }
}

如果正在讀取字符串,您應該能夠作為字符串數組傳遞。

如果要編寫它們,則必須將參數聲明為IntPtrs ,為它們分配內存,然后自己編組數據(此外,您還需要IntPtrs分配內存)。

如果您這樣調用會發生什么情況(argc:= 2):

    if ((res = mysql_server_init(2, argv, groups)) == 1) 
    { 
        Console.WriteLine("MySQL Library Init Failed with error code: %d", res); 
        return false; 
    } 

在我看來,你有一個小錯誤,導致mysql_server_init讀取超出數組邊界。 3替換為2並刪除第三個數組條目。 默認封送程序將完成剩下的工作。

public static bool Start()
{
    string[] argv = new string[3];
    argv[0] = "mysql_test";
    argv[1] = "--datadir=C:/MYSQLTEST";

    string[] groups = new string[3];
    groups[0] = "libmysqd_server";
    groups[1] = "libmysqd_client";

    int res;

    if ((res = mysql_server_init(2, argv, groups)) == 1)
    {
        Console.WriteLine("MySQL Library Init Failed with error code: %d", res);
        return false;
    }
}

更新

此線程中 ,您根本不應使用mysql_server_init ,而應使用mysql_library_init

  1. “ argv”和“ groups”都由庫存儲並在以后使用。 這是一個嚴重的問題,因為如果使用P / Invoke封送處理,則函數返回后,.NET傳遞給該函數的指針將變得無效。 當庫稍后嘗試引用argv或組時,除了在那里,它什么也找不到,這會導致意外行為或崩潰。

如果您使用的是MySQL 5.0.3或更高版本,請嘗試使用mysql_library_init - 它會生成argv和groups的內部副本,因此您可以毫無困難地繼續使用P / Invoke編組(只要您向其添加空條目)組末尾)。 否則,您必須為數組和每個字符串自己分配內存,以確保只要程序正在運行,指針就保持有效。

所以,如果你可以切換到使用mysql_library_init ,我建議這樣做。 副手編組不是一項微不足道的工作(但也不是太難)。

C ++方法采用一個int和兩個char **作為參數,但是有人告訴我,以空終止的string []數組在C#中就足夠了。 由於這是您應該調用的第一種方法,因此我對該問題有些茫然。

到底是誰告訴你的?

我確實相信您可以使用對char []的引用

[DllImport(“libmysqld.dll”)] static extern int mysql_server_init(int argc,ref char [] argv,ref char [] groups);

確保調用約定匹配否則您將遇到問題。

米奇·惠特(Mitch Wheat)的答案可以通過以下線程來增強: 在C#中編組char **

一些附加信息: C#編組char **和unsigned char **

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM