Debugging DLLImport in C#

◇◆丶佛笑我妖孽 提交于 2020-01-15 09:01:00

问题


I have been attempting to get the MySQL Embedded Library working in my C# application for the past 12 hours or so, and have been stuck for quite some time. I am getting the following error when I call mysql_server_init()...

Unhandled Exception: System.AcessViolationException: Attempted to read or write protected memory.

The C++ method takes an int and two char** as parameters, but I was told a null terminated string[] array would suffice in C#. As this is the first method that you're supposed to call, I am somewhat at a loss as to this issue.

Here's my code...

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;
    }
}

回答1:


It seems to me that you have a tiny error, causing mysql_server_init to read beyond the array boundaries. Replace 3 with 2 and remove the third array entry. The default marshaler will do the rest.

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;
    }
}

Update

From this thread, you should not use mysql_server_init at all, but mysql_library_init instead:

  1. Both 'argv' and 'groups' are stored by the library and used later. This is a serious problem, because if you use P/Invoke marshaling, the pointers that .NET passes to the function will become invalid as soon as the function returns. When the library later tries to refer to argv or groups, it'll find nothing but garbage there, causing unexpected behavior or a crash.

If you're using MySQL 5.0.3 or later, try using mysql_library_init instead - it makes an internal copy of argv and groups, so you can keep using P/Invoke marshaling with no trouble (as long as you add a null entry to the end of groups). Otherwise, you'll have to allocate the memory yourself for the arrays and each string, to make sure the pointers stay valid as long as your program is running.

So, if you can switch to using mysql_library_init, I'd suggest doing so. By-hand marshaling is not a trivial undertaking (but not too hard either).




回答2:


If the strings are being read from, you should be able to pass as an array of strings.

If they are being written to, then you will have to declare the parameters as IntPtrs, allocate the memory for them, and then marshal the data yourself (plus you will need to unallocate the memory as well).

what happens if you call like so (argc := 2):

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



回答3:


The C++ method takes an int and two char** as parameters, but I was told a null terminated string[] array would suffice in C#. As this is the first method that your supposed to call, I am at somewhat of a loss as to the issue.

Who exactly told you this?

I do believe you could just use a reference to a char[]

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

Be sure the calling convention matches otherwise you will run into issues.

Mitch Wheat's answer can be enchanced by this thread: Marshalling a char** in C#

Some Additional Information: C# Marshalling char** and unsigned char**



来源:https://stackoverflow.com/questions/7822686/debugging-dllimport-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!