访问违规读取位置传递指针以在c中写入的DLL中起作用
access violation reading location when passing pointers to function in DLL written in c
我正在尝试调用一个在方言之间转换SQL查询的函数。我正在使用开源项目的DLL在C#大学项目中使用这些功能进行转换。我面临的问题是我正在遇到访问违规的阅读地点。
我已经在堆栈溢出上阅读了一些帖子,这表明某处可能有一个坏的指针,但我找不到哪里。我的指针没有损坏
转换的功能是:
int ConvertSql(void *parser, const char *input, int64_t size, const char
**output, int64_t *out_size, int64_t *lines)
{
if(parser == NULL)
return -1;
SqlParser *sql_parser = (SqlParser*)parser;
// Run conversion
sql_parser->Convert(input, size, output, out_size, lines);
return 0;
}
我在C#
中调用该功能 char *parentInput;
fixed(char *input = &inputStr.ToCharArray()[0])
{
parentInput = input;
}
char** output = null;
Int64 out_size = 0;
Int64 lines = 0;
Int64 size = inputStr.Length;
Console.WriteLine(new IntPtr(&out_size)+" "+ new IntPtr(&lines)+" "+new IntPtr(&parserObj)+" "+new IntPtr(output));
int result = ConvertSql(&parserObj, intputStr, size, output, &out_size, &lines);
我从此代码中获取我的解析器对象,该对象无需错误:
IntPtr parserObj = CreateParserObject();
函数的dllimport正在使用此代码:
[DllImport(dllName: "PATHTODLLFOLDER\sqlparser.dll", EntryPoint = "CreateParserObject", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateParserObject();
[DllImport(dllName: "PATHTODLLFOLDER\sqlparser.dll", EntryPoint = "ConvertSql", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern int ConvertSql(void *parser, String input, Int64 size, char **output, Int64 *out_size, Int64 *lines);
在.net中,通过p/indoke调用一个不受管理的方法(这是您称为 extern
方法时发生的情况(涉及各种类型的转换参数,这被称为" marshalling"并且由称为"卫生机"的运行时自动完成。
一般而言,这是元帅指针的一个可怕想法。相反,通过更改P/调用方法的签名来使用CLR MASHALLER将某些类型转换为指针的能力:
// split on multiple lines for readability
[DllImport("PATHTODLLFOLDER\sqlparser.dll", EntryPoint = "ConvertSql", CallingConvention = CallingConvention.Cdecl)]
public static extern int ConvertSql(
IntPtr parser,
[MarshalAs(UnmanagedType.LPStr)] string input,
long size,
out IntPtr output, // see explanation below
out long out_size,
out long lines);
关于上述内容的几件事。首先,我自由使用C#类型别名(字符串,长(,因为这是更惯用的C#,但它不会改变行为。另外,由于不再有指针,因此不需要unsafe
。
首先,我将parser
宣布为IntPtr
,因为如果需要,它们会自动转换为void*
,这就是CreateParserObject()
已经返回的。
其次,可以将参数转换为指示器转换为非初始化的对象,因此,通过将out_size
和lines
标记为out
,您可以解决其他问题。
input
是一个字符串,它具有.net中的特定格式。由于您的功能需要const char*
,因此您需要告诉卫生员如何转换字符。这就是MarshalAs
属性所在的地方:默认转换对您不起作用的时候。UnmanagedType.LPStr
在这种情况下表示char*
,因此字符串会转换。运行时将为您管理内存。
但是在这里,我们在道路上遇到了一个大障碍:输出。编造事物时,总会有关于终生的疑问,或者是特别是:谁发布了记忆?output
是char**
,这一事实意味着解析器分配了一个内存块,然后将其返回,这意味着呼叫者必须释放它。从一开始,由于呼叫者不知道如何分配内存,因此C 设计不良。是malloc
吗?new[]
?平台特定的API(例如LocalAlloc
(?它是指向静态内存块的指针吗?通常,这些API随附文档,确切地告诉您完成指针后如何处理它。良好的C API返回智能指针,或要求呼叫者通过以前分配的内存块,然后可以使用。
但是,这是您正在玩的事情,因此这是使其正常工作的方法。首先,您会认为您可以将output
声明为[MarshalAs(UnmanagedType.LPStr)] out string
:MARSHALLER会将字符复制到托管字符串中并返回...但是随后本机字符串(在C 侧(内存将泄漏,因为运行时没有运行时知道字符串是如何分配的,因此更喜欢对此不做任何事情。另外,假设字符串是无效的,可能并非总是如此。
因此,另一个选择是将output
声明为out IntPtr
。然后,您可以使用Marshal.PtrToStringAnsi
将指针转换为字符串,然后将其释放...但是您需要首先知道它是如何分配的。
将它们放在一起:
var parserObj = CreateParserObject();
var output = IntPtr.Zero;
try
{
long lines;
long out_size;
int result = ConvertSql(parserObj, inputStr, inputStr.Length, out output, out out_size, out lines);
var outputStr = Marshal.PtrToStringAnsi(output, (int)out_size);
// do what you want with outputStr here
}
finally
{
if (output != IntPtr.Zero)
{
// release output here
}
}
哦,还有一个最后的想法:CreateParserObject()
返回的任何内容都可能必须在某一时刻释放。您可能需要另一个功能,可能是:
[DllImport(/* ... */)]
public static extern void DestroyParserObject(IntPtr parserObject);
它甚至可能已经存在于您的DLL中。
祝你好运!
- C++/CLI 混合托管/本机 DLL 不起作用
- 可视C++:XGBoost 从 DLL 调用时不起作用
- PlayFunction在DLL中不起作用,但在独立的exe中工作
- 访问违规读取位置传递指针以在c中写入的DLL中起作用
- DLL函数在VBA环境中不起作用,但在Excel VBA中工作
- 由于mcordbi.dll的错误版本,托管调试不再起作用
- 将 DLL 附加到托管进程不起作用
- 在 DLL 中使用时,运行代码不起作用
- boost::从 DLL 调用时日志格式不起作用
- 在 Windows 8 中编译的 DLL 在 Windows 7 中不起作用
- DLL注入仅在没有从视觉工作室开始时起作用
- 编译错误libgcc_s_dw2-1.dll缺少任何内容都不起作用
- 64位DLL中的CreateThread不起作用
- 将DLL与python一起使用(使用ctypes),不起作用
- GetFullPathNameA的Dll注入不起作用
- 注入dll在windows XP上不起作用
- C# COM-Interop dll for C++ COM dll 在 2 个解决方案之间不起作用
- 在Windows 7下编译的Dll在Windows XP中不起作用
- 线程对象的 WaitForSingleObject 在 DLL 卸载中不起作用
- 这个简单的C++ DLL 在 C# 中不起作用