Mengonversi fungsi dari Visual Basic 6.0 ke C# memunculkan AccessViolationException

Saya mengonversi fungsi dari Visual Basic 6.0 sebagai:

Declare Function RequestOperation Lib "archivedll" (ByVal dth As Long, ByVal searchRequestBuf As String, ByVal buflen As Long, ByVal FieldNum As Long, ByVal OP As Long, ByVal value As String) As Long

Di C#, saya mendeklarasikan fungsinya sebagai:

[DllImport("archivedll")]
public static extern int RequestOperation(int dth ,StringBuilder searchRequestBuf, int bufferLen, int fieldNum, int op, string value);

Saat memanggil RequestOperation dari C#, ia memunculkan pengecualian:

[System.AccessViolationException] = {"Mencoba membaca atau menulis memori yang dilindungi. Ini sering kali merupakan indikasi bahwa memori lain rusak."}

Saya telah berhasil memanggil banyak fungsi lain seperti ini, tetapi hanya fungsi ini yang memberikan pengecualian.


person Thai Vong    schedule 10.11.2009    source sumber


Jawaban (3)


Fungsi ini jelas tidak memunculkan AccessViolationException - sebaliknya, fungsi ini menghasilkan kesalahan pelanggaran akses dengan "mencoba membaca atau menulis memori yang dilindungi". .NET menerjemahkan kesalahan itu menjadi AccessViolationException.

Anda harus mencari tahu mengapa ia "mencoba membaca atau menulis memori yang dilindungi". Secara khusus, apakah Anda menginisialisasi StringBuilder yang Anda teruskan? Silakan posting kode yang Anda gunakan untuk memanggil metode ini.

person John Saunders    schedule 10.11.2009
comment
Ya, saya telah menginisialisasi StringBuilder dengan Capicity = 4096 kode Vb6 yang memanggil Dim bufSearchRequest As String * 4096 retCode = SearchRequestOperation(hDocumentType, bufSearchRequest, Len(bufSearchRequest), fieldIdx, queryType, stringQuery) dan ini adalah panggilan C# StringBuilder searchRequest = new StringBuilder(4096 ); retCode = RequestOperation(hDocumentType, searchRequest, searchRequest.Capacity, indeks, queryType, query); - person Thai Vong; 10.11.2009
comment
Seperti yang dikatakan Eran, kesalahan ini jelas terjadi karena Anda meneruskan objek StringBuilder ke fungsi yang mengharapkan string. Mereka tidak bisa dipertukarkan. - person Alex Warren; 10.11.2009
comment
Eran salah. DLL mengembalikan string melalui argumen searchRequestBuf. Oleh karena itu StringBuilder harus digunakan. String hanya dapat digunakan jika DLL tidak mengubah string masukan. Lihat misalnya di sini. msdn.microsoft.com/en-us/library/ms235282 (VS.80).aspx - person MarkJ; 10.11.2009
comment
@ThaiV Bisakah Anda menjelaskan mengapa Anda menerima jawaban ini? Apakah menginisialisasi StringBuffer menyelesaikan masalah? - person MarkJ; 10.11.2009
comment
@ThaiV: Apakah jawaban ini membantu Anda? - person John Saunders; 10.11.2009

Saya pikir StringBuilder dalam deklarasi fungsi ada hubungannya dengan itu. Anda sebaiknya menggunakan String biasa saja.

person Eran Betzalel    schedule 10.11.2009
comment
Tipe parameter StringBuilder digunakan untuk [OutAttribute] - person Thai Vong; 10.11.2009
comment
Menurutku itu tidak penting. Namun demikian, Anda tidak punya alasan untuk menggunakan StringBuilder sebagai parameter karena seharusnya membangun string dalam kinerja yang dioptimalkan dan tidak diteruskan sebagai wadah data. - person Eran Betzalel; 10.11.2009
comment
-1 Eran, kamu salah. DLL mengembalikan string melalui argumen searchRequestBuf. Oleh karena itu StringBuilder harus digunakan - String tidak dapat digunakan karena string .NET tidak dapat diubah. Lihat misalnya di sini di MSDN msdn.microsoft.com/en -us/library/ms235282(VS.80).aspx - person MarkJ; 10.11.2009
comment
Wow, itu sungguh aneh... Saya rasa Anda hanya bisa mengharapkan implementasi kasar ini dari Microsoft. Maksud saya - Ini adalah Pembuat String, ia membangun string... apa hubungannya dengan meneruskan data dengan ref?! - person Eran Betzalel; 10.11.2009
comment
Mekanisme P/Invoke dari .NET mengatur data antara kode yang dikelola dan tidak dikelola. Ini menyusun data string [keluar] menjadi StringBuilder dengan baik. Anda harus membaca tentang P/Invoke sebelum menyebutnya kasar. - person John Saunders; 10.11.2009
comment
Saya tahu apa yang dilakukan P/Invoke. Bagian StringBuilder di P/Invoke - Saya tidak tahu dan tidak pernah menggunakannya. Bagi saya, ini masih terlihat seperti desain kasar untuk menggunakan kelas bernama StringBuilder untuk menghasilkan data string. - person Eran Betzalel; 11.11.2009
comment
Ini digunakan untuk parameter out di mana fungsi itu sendiri menulis ke dalam buffer string yang Anda berikan padanya. Satu-satunya kelas .NET yang menyediakan korespondensi yang masuk akal untuk buffer string yang dapat diubah adalah StringBuilder. - person Pavel Minaev; 01.12.2009
comment
Memang, karenanya - desain yang kasar. - person Eran Betzalel; 02.12.2009
comment
Bagaimana Anda mendesainnya agar tidak kasar? - person John Saunders; 03.12.2009
comment
Saya akan menggunakan nama yang berbeda dari StringBuilder. Saya akan menggunakan StringBuilder untuk tujuan penggunaannya - untuk membangun string dengan efisiensi optimal. - person Eran Betzalel; 04.12.2009

/// Return Type: int
///dth: int
///searchRequestBuf: BSTR->OLECHAR*
///buflen: int
///FieldNum: int
///OP: int
///value: BSTR->OLECHAR*
[System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="RequestOperation")]

public static extern int RequestOperation(int dth, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.BStr)] string searchRequestBuf, int buflen, int FieldNum, int OP, [System.Runtime.InteropServices.MarshalAsAttribute( System.Runtime.InteropServices.UnmanagedType.BStr)] nilai string);

person Sheng Jiang 蒋晟    schedule 10.11.2009
comment
Dalam pernyataan VB6 Declare, String ByVal disusun sebagai penunjuk ke string ANSI, bukan BSTR. Kalau mau ditulis seperti itu, harus System.Runtime.InteropServices.UnmanagedType.LPStr kedua kali - person MarkJ; 11.11.2009