การแปลงฟังก์ชันจาก Visual Basic 6.0 เป็น C# กำลังทำให้เกิด AccessViolationException

ฉันกำลังแปลงฟังก์ชันจาก Visual Basic 6.0 เป็น:

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

ใน C # ฉันประกาศฟังก์ชันเป็น:

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

เมื่อเรียก RequestOperation จาก C# มันจะส่งข้อยกเว้น:

[System.AccessViolationException] = {"พยายามอ่านหรือเขียนหน่วยความจำที่ได้รับการป้องกัน ซึ่งมักบ่งชี้ว่าหน่วยความจำอื่นเสียหาย"}

ฉันประสบความสำเร็จในการเรียกใช้ฟังก์ชันอื่น ๆ มากมายเช่นนี้ แต่มีเพียงฟังก์ชันนี้เท่านั้นที่ส่งข้อยกเว้น


person Thai Vong    schedule 10.11.2009    source แหล่งที่มา


คำตอบ (3)


เห็นได้ชัดว่าฟังก์ชันนี้ไม่ได้ส่ง AccessViolationException - แต่กลับสร้างข้อผิดพลาดการละเมิดการเข้าถึงโดย "พยายามอ่านหรือเขียนหน่วยความจำที่ได้รับการป้องกัน" .NET กำลังแปลข้อผิดพลาดนั้นเป็น AccessViolationException

คุณจะต้องหาสาเหตุว่าทำไม "พยายามอ่านหรือเขียนหน่วยความจำที่ได้รับการป้องกัน" โดยเฉพาะอย่างยิ่ง คุณได้กำหนดค่าเริ่มต้น StringBuilder ที่คุณส่งต่อหรือไม่ กรุณาโพสต์รหัสที่คุณใช้เรียกวิธีนี้

person John Saunders    schedule 10.11.2009
comment
ใช่ ฉันได้เริ่มต้น StringBuilder ด้วย Capicity = 4096 รหัส Vb6 ที่เรียก Dim bufSearchRequest As String * 4096 retCode = SearchRequestOperation(hDocumentType, bufSearchRequest, Len(bufSearchRequest), fieldIdx, queryType, stringQuery) และนี่คือ C # ที่เรียก StringBuilder searchRequest = new StringBuilder (4096 ); retCode = RequestOperation (hDocumentType, searchRequest, searchRequest.Capacity, ดัชนี, queryType, แบบสอบถาม); - person Thai Vong; 10.11.2009
comment
ดังที่ Eran กล่าวไว้ ข้อผิดพลาดเกิดขึ้นอย่างชัดเจนเนื่องจากคุณกำลังส่งวัตถุ StringBuilder ไปยังฟังก์ชันที่คาดว่าจะมีสตริง พวกเขาไม่สามารถใช้แทนกันได้ - person Alex Warren; 10.11.2009
comment
เอรันพูดไม่ถูก DLL กำลังส่งคืนสตริงผ่านอาร์กิวเมนต์ searchRequestBuf ดังนั้นจึงจำเป็นต้องใช้ StringBuilder สตริงสามารถใช้ได้เฉพาะในกรณีที่ DLL ไม่ได้แก้ไขสตริงอินพุต ดูตัวอย่างที่นี่ msdn.microsoft.com/en-us/library/ms235282 (VS.80).aspx - person MarkJ; 10.11.2009
comment
@ThaiV คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงยอมรับคำตอบนี้? การเริ่มต้น StringBuffer ช่วยแก้ปัญหาได้หรือไม่ - person MarkJ; 10.11.2009
comment
@ThaiV: คำตอบนี้ช่วยคุณได้ไหม? - person John Saunders; 10.11.2009

ฉันคิดว่า StringBuilder ในการประกาศฟังก์ชันมีส่วนเกี่ยวข้องกับมัน คุณควรใช้เพียง String ธรรมดาแทน

person Eran Betzalel    schedule 10.11.2009
comment
ประเภทพารามิเตอร์ StringBuilder ใช้สำหรับ [OutAttribute] - person Thai Vong; 10.11.2009
comment
ฉันไม่คิดว่ามันเป็นเรื่องสำคัญ อย่างไรก็ตาม คุณไม่มีเหตุผลที่จะใช้ StringBuilder เป็นพารามิเตอร์ เนื่องจากควร สร้างสตริง ในประสิทธิภาพที่ได้รับการปรับปรุงให้เหมาะสม และไม่ส่งผ่านเป็นที่เก็บข้อมูล - person Eran Betzalel; 10.11.2009
comment
-1 เอรัน คุณไม่ถูกต้อง DLL กำลังส่งคืนสตริงผ่านอาร์กิวเมนต์ searchRequestBuf ดังนั้นจึงต้องใช้ StringBuilder - ไม่สามารถใช้ String ได้เนื่องจากสตริง .NET ไม่เปลี่ยนรูป ดูตัวอย่างที่นี่ใน MSDN msdn.microsoft.com/en -us/library/ms235282(VS.80).aspx - person MarkJ; 10.11.2009
comment
ว้าว มันแปลกจริงๆ... ฉันเดาว่าคุณสามารถคาดหวังการใช้งานอย่างหยาบๆ จาก Microsoft เท่านั้น ฉันหมายถึง - มันคือ String Builder มันสร้างสตริง ... มันเกี่ยวอะไรกับการส่งผ่านข้อมูลโดยการอ้างอิง! - person Eran Betzalel; 10.11.2009
comment
กลไก P/Inrigg ของข้อมูล .NET marshals ระหว่างโค้ดที่ได้รับการจัดการและไม่ได้รับการจัดการ มันจัดเรียงข้อมูลสตริง [out] ให้เป็น StringBuilder ได้ดี คุณควรอ่าน P/Inrigg ก่อนที่จะเรียกมันว่าหยาบคาย - person John Saunders; 10.11.2009
comment
ฉันรู้ว่า P/Inrigg ทำอะไร ส่วน StringBuilder ที่ P/Inrigg - ฉันไม่รู้และไม่เคยได้ใช้มันเลย สำหรับฉันยังคงดูเหมือนเป็นการออกแบบที่หยาบเพื่อใช้คลาสที่เรียกว่า StringBuilder เพื่อส่งออกข้อมูลสตริง - person Eran Betzalel; 11.11.2009
comment
ใช้สำหรับพารามิเตอร์ out โดยที่ฟังก์ชัน เขียน ลงในบัฟเฟอร์สตริงที่คุณระบุ คลาส .NET เดียวที่ให้ความสอดคล้องที่เหมาะสมสำหรับบัฟเฟอร์สตริงที่ไม่แน่นอนคือ StringBuilder - person Pavel Minaev; 01.12.2009
comment
แท้จริงแล้วด้วยเหตุนี้ - การออกแบบที่หยาบ - person Eran Betzalel; 02.12.2009
comment
คุณจะออกแบบอย่างไรให้ไม่หยาบ? - person John Saunders; 03.12.2009
comment
ฉันจะใช้ชื่ออื่นที่ไม่ใช่ StringBuilder ฉันจะใช้ StringBuilder ตามจุดประสงค์การใช้งาน - เพื่อสร้างสตริงที่มีประสิทธิภาพสูงสุด - 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")]

สาธารณะคงที่ภายนอก int RequestOperation (int dth, [System.Runtime.InteropServices.MarshalAsAttribute (System.Runtime.InteropServices.UnmanagedType.BStr)] สตริง searchRequestBuf, int buflen, int FieldNum, int OP, [System.Runtime.InteropServices.MarshalAsAttribute ( System.Runtime.InteropServices.UnmanagedType.BStr)] ค่าสตริง) ;

person Sheng Jiang 蒋晟    schedule 10.11.2009
comment
ในคำสั่ง VB6 Declare สตริง ByVal จะถูกจัดเรียงเป็นตัวชี้ไปยังสตริง ANSI ไม่ใช่ BSTR หากคุณต้องการเขียนแบบนั้น ควรเป็น System.Runtime.InteropServices.UnmanagedType.LPStr ทั้งสองครั้ง - person MarkJ; 11.11.2009