ข้อผิดพลาดในการล็อคตัวโหลด


95

ฉันกำลังสร้าง C ++ dll โดยเขียนโค้ดใน C #

ฉันได้รับข้อผิดพลาดพูดว่า

ตรวจพบ LoaderLock ข้อความ: กำลังพยายามดำเนินการจัดการภายใน OS Loader lock อย่าพยายามเรียกใช้โค้ดที่มีการจัดการภายในฟังก์ชันเริ่มต้น DllMain หรือรูปภาพเนื่องจากการทำเช่นนั้นอาจทำให้แอปพลิเคชันค้าง

ฉันพยายามค้นหาความหมายของข้อผิดพลาดนี้ แต่ฉันกำลังวาดบทความที่ไม่มีจุดหมายส่วนใหญ่บอกว่าเป็นเพียงคำเตือนและฉันควรปิดสิ่งนั้นใน Visual Studio วิธีแก้ปัญหาอื่น ๆ อาจเกิดจาก iTunes หรือปัญหานี้เกิดขึ้นเมื่อเขียนโปรแกรมด้วย DirectX ปัญหาของฉันเชื่อมต่อกับไม่ได้

มีใครอธิบายได้ไหมว่านี่หมายถึงอะไร?


ฉันรู้สึกกับคุณฉันมีปัญหาเดียวกันและสิ่งที่ทำให้ฉันประหลาดใจที่สุด: dll ของฉันไม่ใช่แม้แต่รหัสที่มีการจัดการดังนั้นทำไม / ควรใช้รหัสที่มีการจัดการใน DllMain (ไม่มีอยู่จริง) อย่างไร ??
แซม

ฉันได้รับคำเตือนนี้ขณะพยายามดูเนื้อหาของชุดข้อมูลในโหมดดีบัก ฉันใช้ c # มันเกิดขึ้นในรูปแบบ windows ปกติ
Soenhay

เนื่องจากคุณไม่สามารถหาสาเหตุได้ (ตามที่คุณแสดงความคิดเห็นในคำตอบด้านบน) ฉันจึงสงสัยว่ามี dll ที่คุณกำลังโหลดซึ่งกำลังก่ออาชญากรรม
John Thoits

คำตอบ:


70

คุณต้องไปที่เมนู Debug -> ข้อยกเว้นเปิด Managed Debugging Assistants ค้นหา LoaderLock และยกเลิกการเลือก

http://goo.gl/TGAHV


22
ใช่นี่คือวิธีปิดคำเตือน แต่หลังจากผ่านไป 2 ปีฉันก็ยังไม่ทราบสาเหตุว่าทำไมจึงเกิดขึ้น
Devdatta Tengshe

2
สิ่งนี้เกิดขึ้นกับฉันเปิดโครงการเก่าใน VS 2012
4imble

1
ฉันอยู่กับคุณ @Kohan ฉันได้เปิดโครงการที่เก่ากว่าและได้รับข้อผิดพลาด ฉันได้ปิดใช้งานข้อยกเว้นนี้แล้ว แต่ต้องการทำความเข้าใจว่าจะทำอย่างไรเพื่อป้องกันปัญหานี้
Pimenta

1
ถ้าฉันรันโปรเจ็กต์เป็นการดีบักแบบเนทีฟโดยมีข้อยกเว้นทั้งหมดตามค่าเริ่มต้น (รีเซ็ตทั้งหมด) หน้าต่างดีบักจะแสดง <mda: msg xmlns: mda = " schemas.microsoft.com/CLR/2004/10/mda "> <! - - พยายามดำเนินการจัดการภายใน OS Loader lock .... ฯลฯ -> <mda: loaderLockMsg break = "true" /> </ mda: msg> VS จากนั้นจะแสดงจุดพักหลายจุดในระหว่างลำดับ CTOR การปิดการตั้งค่า LoaderLock ไม่ได้ช่วยอะไร สำหรับฉันฉันต้องทำเครื่องหมายที่ตัวเลือก MDA ด้านบน (สำหรับ MDA ทั้งหมด) จากนั้นยกเลิกการเลือกตัวเลือกระดับบนสุด (สำหรับไม่มี MDA) จากนั้นสร้าง + เรียกใช้ สิ่งนี้ไม่ได้ผลสำหรับเพื่อนร่วมงานของฉัน
GilesDMiddleton

17
อยากจะแบ่งปันการปรับปรุงใน VS2015 Debug->Windows->Exception Settingsตอนนี้คุณต้องไปที่ ส่วนที่เหลือเหมือนกันกับManaged Debugging Assistants \ LoaderLock
jxramos

52

แนวคิดทั่วไปของการล็อคตัวโหลด: ระบบเรียกใช้รหัสใน DllMain ภายในล็อค (เช่นเดียวกับการล็อคการซิงโครไนซ์) ดังนั้นการใช้รหัสที่ไม่น่ารำคาญภายใน DllMain คือ "ขอหยุดชะงัก" ตามที่อธิบายไว้ที่นี่

คำถามคือทำไมคุณถึงพยายามรันโค้ดภายใน DllMain จำเป็นหรือไม่ที่โค้ดนี้จะทำงานในบริบทของ DllMain หรือคุณสามารถสร้างเธรดใหม่และรันโค้ดในนั้นได้และไม่ต้องรอให้โค้ดทำงานใน DllMain ให้เสร็จสิ้น

ฉันเชื่อว่าปัญหาเกี่ยวกับโค้ดที่ยุ่งยากโดยเฉพาะคือการเรียกใช้โค้ดที่มีการจัดการอาจเกี่ยวข้องกับการโหลด CLR และสิ่งนั้น ๆ และไม่มีทางรู้ว่าจะเกิดอะไรขึ้นที่นั่นซึ่งจะส่งผลให้เกิดการชะงักงัน ... ฉันจะไม่ปฏิบัติตามคำแนะนำของ "ปิดการใช้งานคำเตือนนี้ "ถ้าฉันเป็นคุณเพราะมีโอกาสมากที่คุณจะพบว่าแอปพลิเคชันของคุณค้างโดยไม่คาดคิดภายใต้สถานการณ์


4
ฉันกำลังทำงานกับแอปพลิเคชัน Direct3D นี่คือ EXE อย่างไรก็ตามฉันยังคงเห็นข้อผิดพลาดนี้ มีแนวคิดอย่างไรในการแก้ไขปัญหานี้ให้ดีที่สุด
Agnel Kurian

18

อัปเดตสำหรับ. NET 4.0 และกรอบข้อมูลล่าสุดเพิ่มเติม

นี่เป็นคำถามเก่าที่ถูกถามในช่วงเวลาของ. Net 2.0 เมื่อการสนับสนุน DLL ในโหมดผสมมีปัญหาในการเริ่มต้นที่รุนแรงมีแนวโน้มที่จะเกิดการหยุดชะงักแบบสุ่ม ตั้งแต่. Net 4.0 การเริ่มต้นของ DLL ในโหมดผสมมีการเปลี่ยนแปลง ตอนนี้มีการเริ่มต้นสองขั้นตอนแยกกัน:

  1. การเริ่มต้นดั้งเดิมเรียกที่จุดเริ่มต้นของ DLL ซึ่งรวมถึงการตั้งค่ารันไทม์ C ++ ดั้งเดิมและการเรียกใช้เมธอด DllMain ของคุณ
  2. การเริ่มต้นที่มีการจัดการดำเนินการโดยอัตโนมัติโดยตัวโหลดระบบ

เนื่องจากขั้นตอน # 2 ดำเนินการนอก Loader Lock จึงไม่มีการหยุดชะงัก โดยมีรายละเอียดอธิบายไว้ที่การเริ่มต้นของการประกอบผสม

เพื่อให้แน่ใจว่าแอสเซมบลีโหมดผสมของคุณสามารถโหลดจากปฏิบัติการเนทีฟได้สิ่งเดียวที่คุณต้องตรวจสอบคือเมธอด DllMain ถูกประกาศเป็นโค้ดเนทีฟ #pragma unmanagedสามารถช่วยได้ที่นี่:

#pragma unmanaged

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
    )
{
    ... // your implementation here
}

สิ่งสำคัญคือรหัสใด ๆ ที่ DllMain อาจเรียกโดยตรงหรือโดยอ้อมจะไม่ได้รับการจัดการด้วย มันทำให้รู้สึกที่จะ จำกัด ประเภทของฟังก์ชั่นการใช้งานโดย DllMain เพื่อให้คุณสามารถเข้าถึงได้ติดตามทุกรหัสจาก DllMain #pragma unmanagedและให้แน่ใจว่ามันคือทั้งหมดที่รวบรวมกับ

คอมไพเลอร์ช่วยเล็กน้อยโดยให้คุณอุ่น C4747 หากตรวจพบว่า DllMain ไม่ได้รับการประกาศว่าไม่มีการจัดการ:

1>  Generating Code...
1>E:\src\mixedmodedll\dllmain.cpp : warning C4747: Calling managed 'DllMain': Managed code may not be run under loader lock, including the DLL entrypoint and calls reached from the DLL entrypoint

อย่างไรก็ตามคอมไพเลอร์จะไม่สร้างคำเตือนใด ๆ หาก DllMain เรียกใช้ฟังก์ชันที่มีการจัดการอื่น ๆ โดยอ้อมดังนั้นคุณต้องแน่ใจว่าจะไม่เกิดขึ้นมิฉะนั้นแอปพลิเคชันของคุณอาจหยุดชะงักแบบสุ่ม


6

กด ctr d + e จากนั้น Expend Managed Debugging Assistants Node จากนั้นยกเลิกการเลือก LoaderLock

หวังว่านี่จะช่วยคุณได้


ทางลัดคือ alt + d + x
Narayan

3
ทางลัดขึ้นอยู่กับการกำหนดค่าที่คุณระบุให้ใช้ในระหว่างการรันครั้งแรก เค้าโครงทางลัด C # คือ (Ctrl + D, E) (นอกจากนี้คุณสามารถกำหนดคีย์ผสมให้กับฟังก์ชันนี้ได้ในตัวเลือก -> สภาพแวดล้อม -> แป้นพิมพ์)
Adam LS

6

กรุณาเตือนผู้VS2017 ผู้ใช้ที่คุณจำเป็นต้องปิดการใช้งาน " ผู้ช่วยยกเว้น " แทน " ข้อยกเว้นผู้ช่วย " (ก่อน VS2017) เพื่อป้องกันข้อผิดพลาดจากการล็อครถตักดินซึ่งการตั้งค่าเส้นทางDebug-> ข้อยกเว้น เพิ่งใช้ int ถึงปัญหานี้และเสียเวลา 2 ชั่วโมงในการค้นหาวิธีแก้ไข ...


ฉันไม่มี "Exception" ภายใต้ "Debug" ฉันมี VS2017 Community 15.8.4
Alex

@Alex ตรวจหา Debug -> Windows -> Exception Settings หรือกด Ctrl + Alt + E
mistika

4

ฉันเพิ่งได้รับข้อผิดพลาดนี้ขณะสร้างอินสแตนซ์ของ COM-Object ที่เขียนด้วยรหัสดั้งเดิม:

m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy"));

สิ่งนี้นำไปสู่ข้อผิดพลาดที่อธิบายไว้ "LoaderLock ถูกตรวจพบ" - ข้อยกเว้นถูกโยน

ฉันเอาชนะข้อผิดพลาดนี้โดยการสร้าง object-instance ในเธรดเพิ่มเติม:

ThreadStart threadRef = new ThreadStart(delegate { m_ComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Fancy.McDancy")); });
Thread myThread = new Thread(threadRef);

myThread.Start();
myThread.Join(); // for synchronization

ข้อผิดพลาดสามารถเกิดขึ้นได้กับวัตถุที่สามารถถอดเปลี่ยนได้ (MarshalByRefObject) และวิธีนี้ใช้ไม่ได้กับสิ่งเหล่านั้น
Matthieu

3

ฉันกำลังสร้าง C ++ CLR DLL (MSVS2015) ที่ต้องโทรไปยัง DLL ที่ไม่มีการจัดการและกำหนดรหัสที่ไม่มีการจัดการ ฉันใช้ #pragma จัดการและ #pragma ที่ไม่มีการจัดการเพื่อควบคุมโหมดที่อยู่ในพื้นที่ที่กำหนดของโค้ด

ในกรณีของฉันฉันใส่ #pragma ที่ไม่มีการจัดการไว้ด้านหน้า DllMain () ของฉันและสิ่งนี้จะช่วยแก้ปัญหาได้ ดูเหมือนจะคิดว่าฉันต้องการ DllMain () เวอร์ชันที่มีการจัดการ


2

ปัญหานี้เกิดขึ้นเนื่องจากวิธีการที่ดีบักเกอร์ใน Visual Studio เรียกใช้โปรแกรมประยุกต์ที่มีการจัดการที่ใช้ Microsoft Foundation Classes เวอร์ชัน 8.0 ในไฟล์ DLL อย่างน้อยหนึ่งไฟล์

อ่านอย่างละเอียดได้ที่: http://msdn.microsoft.com/en-us/library/aa290048(vs.71).aspx


2

เส้นทางการตั้งค่าในอินสแตนซ์ Visual Studio 2017 ของฉันคือ Debug -> Windows -> Exception Settings การตั้งค่าข้อยกเว้น "หน้าต่าง" ปรากฏขึ้นในกลุ่มแท็บด้านล่าง (ตรงข้ามกับหน้าต่างแยกต่างหาก) ฉันใช้เวลาสักพักกว่าจะสังเกตเห็น ค้นหา "loader"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.