ตัวจัดสรรหน่วยความจำ
บทความนี้ได้รับแจ้งให้ปรับปรุงหลายข้อ กรุณาช่วยปรับปรุงบทความ หรืออภิปรายปัญหาที่หน้าอภิปราย
|
ในการเขียนโปรแกรมคอมพิวเตอร์ภาษาซีพลัสพลัส, allocators หรือ ตัวจัดสรรหน่วยความจำ เป็นคอมโพเนนท์ที่สำคัญใน ไลบรารี่มาตราฐานของ C++ ซึ่งได้กำหนด โครงสร้างข้อมูลหลายตัว อย่างเช่น ลิสต์ (List) หรือ รายการ, เซต (Set) โดยทั่วไปโครงสร้างข้อมูลเหล่านี้รู้จักกันในนาม คอนเทนเนอร์ (Container) ลักษณะโดยทั่วไปของคอนเทนเนอร์คือ ความสามารถที่เปลี่ยนขนาดการจองหน่วยความจำได้ในขณะที่โปรแกรมกำลังทำงาน เพื่อที่จะสามารถกระทำการทำงานเหล่านี้ได้มีความจำเป็นอย่างยิ่งที่ต้องใช้ การจัดสรรหน่วยความจำแบบพลวัต (Dynamic memory allocation) โดยการจัดสรรหน่วยความจำจะจัดการคำร้องขอการจัดสรร (allocation) และยกเลิการจัดสรร (deallocation) หน่วยความจำ ทั้งหมดแก่คอนเทนเนอร์ ไลบรารี่มาตราฐานของ C++ กำหนดให้ รูปแบบการจัดสรรหน่วยความเบื้องต้นให้แก่ผู้ใช้งานตั้งแต่เริ่มต้น อย่างไรก็ตามการปรับแต่งการจัดสรรหน่วยความจำ (Custom allocator) เพิ่มเติมก็สามารถทำได้ด้วยผู้พัฒนาโปรแกรม
ตัวจัดการหน่วยความจำ ที่เป็นส่วนหนึ่งของ Standard Template Library (STL) ถูกคิดค้นโดย Alexader Stepanov พวกเขาเริ่มต้นการคิดค้นเพื่อที่สร้างไลบรารี่ที่สามารถยืดหยุ่น และเป็นอิสระกับแบบจำลองหน่วยความจำระดับล่าง (Underlying memory model) ที่อนุญาตให้ผู้พัฒนาโปรแกรมใช้ตัวชืี้ที่กำหนดเอง (Custom pointer) และ การอ้างถึง ประเภทข้อมูลในไลบรารี่ อย่างไรก็ตามในขั้นตอนของการปรับ STL เข้ากับมาตราฐานของ C++ คณะกรรมการวางมาตราฐาน C++ (C++ standardiaztion committee) ได้ตระหนักถึง การทำแบบจำลองหน่วยความจำในแบบแอ็บสแตรค (Abstraction of the memory model) ทั้งหมด จะส่งผลเสียอย่างมากต่อประสิทธิภาพ จนไม่สามารถยอมรับได้ เพื่อที่จะแก้ไขปัญหานี้ ข้อกำหนดของตัวจัดสรรหน่วยความจำจึงถูกสร้างให้มีข้อจำกัดมากขึ้น ส่งผลให้ ระดับปรับปรุงแก้ใขที่ถูกกำหนดด้วยตัวจัดการหน่วยความจำมีข้อจำกัดกว่าในตอนที่เริ่มต้นในแนวคิดของ Stepanov
แม้กระนั้น ยังคงมีหลายๆ สถานการที่มีความจำเป็นในการปรับปรุงตัวจัดการหน่วยความจำ และในหลายๆเหตุผลในการปรับแต่งตัวจัดการหน่วยความจำนั้น ก็เพื่อเพิ่มประสิทธิ์ภาพในการจัดสรรหน่วยความจำ ให้ใช้หน่วยความจำแบบพูล (Memory pools) และการเอนแคบซูเลท (Encapsulating) การเข้าถึงของประเภทหน่วยความจำหลายชนิด อย่างเช่น หน่วยความจำที่ใช้ร่วมกัน (Shared memory) และ การกำจัดหน่วยความจำที่ไม่ใช้ (Garbage collected memory) โดยเฉพาะอย่างยิ่งโปรแกรมที่ใช้หน่วยความจำขนาดเล็กบ่อยๆ จะได้รับประโยชน์จากการปรับปรุงตัวจัดสรรหน่วยความจำ ทั้งในแง่ของ การทำงานของโปรแกรม และขนาดของการใช้งานหน่วยความจำ
ประวัติ
[แก้]ข้อมูลเพิ่มเติม : Standard Template Library
Alexander Stepanov และ Meng Lee นำเสนอ Standard Template Library (STL) แด่คณะกรรมการวางมาตราฐาน C++ (C++ standardiaztion committee) ใน เดือนมีนาคม 2537[1] แม้ว่าจะประสพปัญหาบ้างแต่ไลบราลี่ก็ได้รับการอนุมัติในเบื้องต้น โดยเฉพาะอย่างยิ่ง Stepanov ได้ถูกร้องขอให้ทำการสร้างไลบรารี่ของคอนเทนเนอร์ ที่เป็นอิสระจากแบบจำลองหน่วยความจำระดับล่าง[2] ซึ่งนำไปสู่การสร้างตัวจัดสรรหน่วยความจำ และในเวลาต่อมา อินเทอร์เฟสของ STL คอนเทนเนอร์ได้ถูกเขียนขึ้นใหม่ เพื่อที่จะสามารถใช้ตัวจัดสรรหน่วยความจำได้
ในการปรับปรุง STL ให้ถูกบรรจุในไลบรารี่มาตราฐานของ C++ Stepanov ได้ทำงานอย่างใกล้ชิดกับสมาชิกในกรรมการวางมาตราฐานบางท่าน ซึ่งประกอบด้วย Andrew Koenig และ Bjarne Stroustrup ซึ่งเป็นคนสังเกตว่า การปรับแต่งตัวจัดสรรหน่วยความจำมีความเป็นไปอย่างมากที่จะดำเนินการในการจัดเก็บ STL คอนเทนเนอร์อย่างถาวร ซึ่งขณะนั้น Stepanov กำลังพิจารณา "important and interesting insight" "ส่วนที่สำคัญและ หน้าสนใจ"[2]
จากมุมมองความสามารถในการโอนย้าย ของอุปกรณ์ที่ถูกกำหนดที่เกี่ยวข้องกับการกล่าวถึง แอดเดรส (Address) พอร์ยเตอร์ (Pointer) และอื่นๆ จะถูกเอนแคปซูเลตไว้ในหน่วยความจำที่มีขนาดเล็กและทำงานอย่างตรงไปตรงมา
—Alex Stepanov, นักออกแบบของ the Standard Template Library |
ในตอนเริ่มต้นข้อเสนอของตัวจัดสรรหน่วยความจำไม่สามารถทำงานร่วมในการใช้งานบางกรณี ที่ยังไม่เป็นที่ยอมรับจากคณะกรรมการวางมาตราฐาน คือความสามารถของการกำหนดชื่อที่ใช้ใน เทมเพลตอาร์กิวเมนต์ (Templat argument) เป็นเทมเพลตของตัวมัน ตั้งแต่ฟีเจอร์ (Feature) แบบนั้นไม่สามารถถูกคอมไพล์ (Compile) ได้ในทุกคอมไพเลอร์ (Compiler) ที่มีในตอนนั้น ตามคำกล่าวของ Stepanov ว่า "ทำให้ Bjarne [Stroustrup] และ Andy [Koenig] ใช้เวลาอย่างมากในการที่ จะพยายามตรวจสอบว่าพวกเราได้ทำการพัฒนาอย่างถูกต้องหรือไม่ กับฟีเจอร์ที่ไม่สามารถใช้งานได้" ทำให้ไลบรารี่ที่เคยให้งานพอร์ยเตอร์ และ เรฟเฟอร์เรนซ์ไทป์โดยตรง ถูกเปลี่ยนมาใช้การอ้างถึง ไทป์โดยตัวจัดสรรหน่วยความจำแทน Stepanov ได้กล่าวถึงตัวจัดสรรหน่วยความจำในตอนหลังว่า "ข้อดีของฟีเจอร์ใน STLคือ การเจาะจงที่จะสนใจแต่ประเภทข้อมูลที่มีขึ้นกับอุปกรณ์(...) ซึ่งถูกเอนแคบซูเลท (Encapsulated) ภายในโค้ดราวๆ 16 บรรทัด"[2]
ในขณะที่ Stepanov เริ่มต้นให้ความสนใจทำการเอนแคปซูเลทแบบจำลองหน่วยความจำทั้งหมดในตัวจัดสรรหน่วยความจำ คณะกรรมการก็ได้ตระหนักถึงความประสิทธิ์ภาพที่ลดลงจนนำไปสู่ระดับที่ไม่สามารถยอมรับได้ของขั้นตอนการทำเอนแคปซูเลท[3][4] เพื่อที่บรรเทาปัญหานี้ ทางคณะกรรมการได้มีการเพิ่มถ้อยคำของเกี่ยวกับประสิทธิ์ภาพในความประสงค์ของการทำตัวจัดสรรหน่วยความจำ โดยเฉพาะอย่างยิ่ง การอิมพลีเมนต์ ตัวบรรจุ หรือ คอนเทนเนอร์ (Container) ซึ่งรวมไปถึงการกำหนดชนิดของตัวจัดสรรหน่วยความจำสำหรับพอร์ยเตอร์ ความสัมพันธ์ของประเภทข้อมูลที่เที่ยบเท่ากับการจัดสรรโดยตัวจัดสรรหน่วยความจำ ทุกๆอินสแตนท์ (Instance) ให้มีค่าเทียบเท่ากับการจุดประสงค์เริ่มต้นของการออกแบบตัวจัดสรรหน่วยความจำ และ ถูกจำกัดอยู่ในการใช้ตัวจัดสรรหน่วยความจำ[4]
ต่อมา Stepanov ได้ให้ความเห็นว่า ในเมือตัวจัดสรรหน่วยความจำ "ไม่ได้เป็นสิ่งที่เลวร้ายใน [แนวคิด] ทางทฤษฏี(...) โชค(ไม่) ดีพวกมัน ไม่สามารถทำได้ในทางปฏิบัติ" เขาสังเกตว่าเพื่อที่จะให้ตัวจัดสรรหน่วยความจำมีประโยชน์อย่างจริงจัง การปรับเปลี่ยน แกนหลักของภาษา (C++) นั้นเป็นสิ่งจำเป็น[5]
ในการปรับปรุงมาตราฐานของ C++ ในปี 2554 ได้ยกเลิกคำสั่งที่ทำให้สับสนของตัวจัดการหน่วยความจำที่ให้ถูกเปรียบเที่ยบกับค่าเท่ากับ และ ถูกใช้เป็นพอร์ยเตอร์ โดยการเปลี่ยนแปลงนี้ทำให้ตัวจัดสรรหน่วยความจำที่เป็น สเตทฟูล (Stateful) สามารถใช้งานได้มากขึ้น และยอมให้ตัวจัดการหน่วยความจำสามารถจัดการ หน่วยความจำร่วมกันที่ไม่อยู่ในโพรเซส (out-of-process shared memory) ได้[6][7] จุดประสงค์ของตัวจัดสรรหน่วยความจำในตอนนี้คือเพื่อให้คนเขียนโปรแกรมสามารถควบคุมหน่วยความจำที่อยู่นอกเหนือกับที่ถูกจัดสรรในคอนเทนเนอร์ และแทนที่จะเป็นการปรับแบบจำลองแอดเดรส (Address model) ที่อยู่ภายใต้ส่วนของฮาร์ดแวร์ (Hardware) ในความเป็นจริงการปรับปรุงมาตราฐานได้ยกเลิกความสามารถของตัวจัดสรรหน่วยความจำที่แสดงถึงการขยายไปยัง แบบจำลองแอดเดรสของ C++ (C++ address model) โดยทั่วไป (และจงใจ) ยกเลิกจุดประสงค์ตั้งแต่เริ่มแรกในการทำตัวจัดสรรหน่วยความจำ[8]
ความต้องการ
[แก้]คลาส (Class)ใดๆที่เติมเต็มสามารถตัวจัดสรรหน่วยสามารถเป็นเสมือนตัวจัดสรรหน่วยความจำ โดยเฉพาะอย่างยิ่ง คลาสที่สามารถจัดสรรหน่วยความจำสำหรับอ็อปเจ็ค (Object) ไทป์ T
ที่ต้องกำหนดประเภทข้อมูล A::pointer, A:const_pointer, A::reference, A::const_reference และ A::value_type
สำหรับการประกาศอ็อปเจ็คทั่วไป และการอ้างอิง (หรือพอร์ยเตอร์) ไปยังอ็อปเจ็คไทป์ T
ซึ่งควรที่จะให้ ไทป์ A::size_type
เป็นข้อมูลประเภทไม่มีสัญญาลักษณ์ที่สามารถรองรับการแสดงข้อมูลขนาดที่ใหญ่ที่สุดของอ็อปเจ็ค A ที่ถูกกำหนดในแบบจำลองตัวจัดสรรหน่วยความจำได้ และคล้ายกับสัญญาลักษณ์ใน A:difference_type
ที่สามารถแสดงความแตกต่างระหว่างพอร์ยเตอร์สองตัวในตัวจัดสรรหน่วยความจำ[9]
แม้ว่าความสอดคล้องในการทำไลบรารี่มาตราฐานที่อนุญาตที่จะอ้างถึง A:pointer
และ A::const_pointer
ของตัวจัดสรรหน่วยความจำเป็น ไทป์เด็ฟส์ (Typedefs) สำหรับ T*
และ T const*,
ไลบรารี่ยังสนับสนุนตัวจัดสรรหน่วยความจำตัวที่เป็น เจนเนอร์รอลไทป์ (General type) ตัวอื่นๆด้วย[10]
ตัวจัดสรรหน่วยความจำ (ในที่นี้ขอกำหนดเป็น A
) สำหรับอ็อปเจ็คประเภท T
จะต้องมีฟังก์ชัน (Function) ที่มีซิกเนเจอร์ (Signature) หรือรูปแบบของอาร์กิวเมนต์(Argrument) ในการเรียกใช้งานฟังก์ชัน ด้วย A::pointer A::allocate (size_type n, A<void>::const_pointer hint = 0)
ฟังก์ชันนี้จะทำการคืนค่าพอร์ยเตอร์ที่ชี้ไปยังอิลิเมนต์ (Element) ตัวแรกของอาเรย์ที่ถูกจัดสรรที่มีขนาดใหญ่พอที่จะรองรับอ็อปเจ็ค n จำนวนที่เป็นไทป์ T
หน่วยความจำเท่านั้นที่ถูกทำการจอง และอ็อปเจ็คยังไม่ได้เกิดการสร้างขึ้นและมากไปกว่านั้น ตัวเลือกพอร์ยเตอร์อาร์กิวเมนต์ (ที่ชี้ไปยังอ็อปเจ็คที่ได้จับจองไว้แล้วด้วย A) สามารถถูกใช้เหมือนการแนะนำเพื่อที่จะดำเนินการเกี่ยวกับที่ของหน่วยความจำใหม่ที่ควรจะจัดสรรตามลำดับเพื่อปรับปรุงหน่วยความจำที่ถูกจอง[11] อย่างไรก็ตามการดำเนินการก็สามารถที่จะละอากิวเมนต์ได้
การสอดคล้องของ void A::deallocate(A::pointer p, A::size_type n) สมาชิกของ
ฟังก์ชันจะยอมรับพอร์ยเตอร์ตัวใดก็ได้ที่สามารถคืนค่าจากการเรืยกใช้ของสามาชิกของฟังก์ชัน A::allocate
ก่อนหน้าและจำนวนอิลิเมนต์ที่ถูกยกเลิกการจัดสรร (Deallocate) แต่ไม่ได้ถูกทำลาย (Destruct)
A::max_size()
เป็นฟังก์ชันที่คืนค่าเป็นจำนวนตัวเลขที่มากพอของอ็อปเจ็คไทป์ T
ที่คาดว่าจะถูกทำการจัดสรรสำเร็จด้วยการเรียกใช้ A::allocate
โดยค่าที่คืนกลับจะเป็น A::size_type(-1) / sizeof (T)
[12] ดังนั้น สมาชิกของฟังก์ชัน A::address
จะคืน A::pointer
ที่ชี้ไปยังแอดเดรสของอ็อปเจ็ค และให้ A:reference
ของอ็อปเจ็ค
อ็อปเจ็คที่ถูกสร้าง (Construct) และถูกทำลาย (Deconstruct) จะถูกจัดการแยกต่างหากจาก การจัดสรร (Allocation) และยกเลิกการจัดสรร (Deallocation) หน่วยความจำ[12] ส่วนตัวจัดสรรหน่วยความจำจะต้องการฟังก์ชัน 2 ตัวคือ A::constuct
และ A::destroy
เพื่อที่จะรองรับอ็อปเจ็คที่ถูกสร้างและถูกทำลายตามลำดับ โดยความหมายของฟังก์ชันควรที่จะเทียบเท่ากับเนื้อความข้างล่างนี้[9]
template <typename T> void A::construct(A::pointer p, A::const_reference t) { new ((void*) p) T(t); } template <typename T> void A::destroy(A::pointer p){ ((T*)p)->~T(); }
โค้ดโปรแกรมข้างบนนี้จะใช้ไวยากรณ์ (Syntax) new
และเรียก destructor ตรงๆ
ตัวจัดสรรหน่วยความจำควรจะทำการสำเนาการสร้าง (Copy-constructible) : ตัวจัดสรรหน่วยความจำของอ็อปเจ็คไทป์ T
สามารถที่จะถูกสร้างจากตัวจัดสรรหน่วยความของอ็อปเจ็คไทป์ U
ถ้าตัวจัดสรรหน่วยความจำ (A
) จัดสรรหน่วยความจำที่บริเวณหน่วยความจำ R
แล้ว R
สามารถถูกยกเลิกการจัดสรรได้ก็ต่อเมื่อเป็นตัวจัดสรรหน่วยความจำที่เทียบได้กับ A
เท่านั้น[9]
ตัวจัดสรรหน่วยความจำยังต้องการได้รับเทมเพลตคลาส template <typename U> struct A::rebind { typedef A<U> other; };
ที่ยินยอมให้อ้างอิงถึงตัวจัดสรรหน่วยความจำ, พารามิเตอร์ในรูปแบบชนิดอื่น ตัวอย่างเช่น การให้ตัวจัดสรรหน่วยความจำ ไทป์ IntAllocator
แก่อ็อปเจ็คประเภท int
ความสัมพันธ์ของตัวจัดสรรหน่วยความจำกับประเภทข้อมูล long
ก็ควรจะได้รับเมื่อมีการใช้ IntAllocator::rebind<long>::other
เช่นกัน[12]
การปรับแต่งตัวจัดสรรหน่วยความจำ
[แก้]ประสิทธิภาพเป็นเหตุผลหลักเหตุอันหนึ่งที่ทำให้ต้องมีการปรับแต่งตัวจัดหน่วยความจำ การใช้ตัวจัดสรรหน่วยความจำที่พิเศษในการเพิ่มประสิทธิ์ภาพ หรือการลดจำนวนการใช้งานหน่วยความจำ หรือทั้งสองอย่าง[4][13] โดยเริ่มต้นตัวจัดสรรหน่วยความจำจะใช้โอเปอเรเตอร์ (Operator) new
ในการจองหน่วยความจำ[14] และบ่อยครั้งที่มีการใช้เป็นเลเยอร์ครอบฟังก์ชันตัวจัดสรรหน่วยความจำแบบฮีป (Heap)[15] ที่จัดการอย่างเหมาะสมกับบล็อคขนาดใหญ่ของหน่วยความจำที่ใช้นานๆครั้งในโปรแกรม ในการใช้งานนี้อาจจะถูกใช้ได้ดีกับคอนเทนเนอร์ขนาดใหญ่ที่จองในหน่วยความจำอย่าง เวคเตอร์ (vector) และ เด็ค (deque - double-ended queue)[13] อย่างไรก็ตามสำหรับคอนเทนเนอร์ที่จำเป็นต้องใช้การจัดสรรสำหรับอ็อปเจ็คขนาดเล็กที่มีลำดับ อย่างเช่น แมค (Map) และ ลิสท์ (list) โดยใช้ตัวจัดสรรหน่วยความจำพื้นฐานจะช้า[4][15] ปัญหาอื่นที่พบบ่อยอย่าง ตัวจัดสรรหน่วยความจำ malloc (malloc-based allocator) ที่ใช้ร่วมกับการอ้างถึงหน่วยความจำเฉพาะที่ (locality of reference)[4] ที่ไม่เหมาะสม และการกระจัดกระจายของหน่วยความจำ (memory fragmentation) ที่มากเกินไป [4][15]
โดยย่อ, ในวรรคนี้ (...) คือ มาตราฐานที่ "ผมฝันไว้" ที่กล่าวถึงตัวจัดสรรหน่วยความจำ จนกว่าความฝันเป็นจริง นักพัฒนาโปรแกรมจะต้องสนใจเกี่ยวกับการการโอนย้ายโปรแกรมจะถูกจำกัดที่ตัวของโปรแกรมที่ทำการปรับแต่งตัวจัดสรรหน่วยความจำโดยไม่มีสถานะ (State)
—Scott Meyers, Effective STL |
วิธีที่นิยมในการปรับปรุงประสิทธิ์ภาพการทำงานคือ การสร้างตัวจัดสรรหน่วยความจำแบบพูล[13] แทนที่จะทำการจองหน่วยความจำในทุกครั้งที่มีการเพิ่มไอเทม หรือการเอาไอเทมออกจากคอนเทนเนอร์ การจองหน่วยความจำขนาดใหญ่ (หน่วยความจำแบบพูล) ไว้ล่วงหน้า หรือถ้าเป็นไปได้ตอนเริ่มเปิดโปรแกรม การตัวจัดสรรหน่วยความจำที่ถูกปรับแต่งจะรองรับการร้องขอการจองหน่วยความจำโดยการคืนค่าของพอร์ยเตอร์ที่ชี้ไปยังหน่วยความจำแบบพูล (Pool memory) จริงๆแล้วการคืนหน่วยความจำสามารถเลือนการทำงานได้จนกว่าจะไม่มีความจำเป็นในการใช้งานหน่วยความจำแบบพูล หรือ อาจกล่าวได้ว่าอายุของหน่วยความจำพูลได้สิ้นสุดลง ตัวอย่างของตัวจัดสรรหน่วยความจำแบบพูลสามารถที่พบได้ในไลบรารี่ Boost ใน C++[13]
หัวข้อการปรับแต่งตัวจัดการหน่วยความจำได้ถูกแก้ไขโดยผู้เชี่ยวขาญ C++ และนักเขียนโปรแกรมหลายต่อหลายคน รวมถึง Scott Meyers จาก Effective STL และ Andrei Alexandrescu จาก Modern C++ Design. Mayers สังเกตว่า ความต้องการสำหรับอินสแตนซ์จากตัวจัดสรรหน่วยความจำมีผลเทียบเท่ากับ ผลกระทบที่ได้รับของการโอนย้ายตัวจัดสรรหน่วยความจำไปยังการไม่มีสถานะ แม้ว่าในมาตราฐานของ C++ จะแสดงถึงไลบรารี่ให้การสนับสนุนตัวจัดสรรหน่วยความจำแบบมีสถานะ (Stateful),[10] Meyers เรียกข้อความวรรคนี้ว่า "a lovely sentiment" that "offers you next to nothing", characterizing the restriction as "draconian"[4]
ในภาษา C++ ของ Bjarne Stroustrup หรืออีกนัยหนึ่งระบุถึง การแสดงการควบคุมอย่างเข้มงวดต่อข้อมูลแต่ล่ะอ็อปเจ็คในตัวจัดสรรหน่วยความจำไม่ได้รุนแรงนัก[3] และชี้ให้เห็นว่าตัวจัดสรรหน่วยความจำส่วนใหญ่ไม่จำเป็นต้องมีสถานะ และจะมีประสิทธิภาพที่ดีขึ้นถ้าไม่มีสถานะ เขากล่าวถึงในกรณี การปรับแต่งตัวจัดสรรหน่วยความจำ(custom allocators), การตั้งชื่อ (Namely), ตัวจัดสรรหน่วยความจำแบบพูล (memory pool allocators), หน่วยความจำแบบแชร์ (shared memory allocators) และตัวกำจัดหน่วยความจำที่ไม่ใช (Garbage collected memory allocator) ซึ่งเขาได้แสดงให้เห็นถึงการดำเนินการสร้างตัวจัดการหน่วยความจำ ที่ใช้หน่วยความจำภายในแบบพูล (internal memory pool) สำหรับการจัดสรรหน่วยความจำอย่างรวดเร็ว และการยกเลิกหน่วยความจำขนาดเล็ก แต่ตั้งข้อสังเกตว่าการดำเนินการที่เหมาะสมอาจจะถูกกระทำโดยตัวจัดสรรหน่วยความจำที่ถูกอิมพลิเมนท์ (Implementation)แล้ว[3]
ในอีกการใช้การปรับแต่งตัวจัดสรรหน่วยความจำสำหรับการแก้ไขการดีบักหน่วยความจำที่เกี่ยวข้องกับข้อผิดพลาด[16] ควรจะแล้วเสร็จด้วยการเขียนตัวจัดสรรหน่วยความจำที่จัดสรรหน่วยความจำเพิ่มขึ้น ในหน่วยความจำที่ทำการเก็บข้อมูลของการดีบัก[17] อย่างตัวจัดสรรหน่วยความจำที่ถูกใช้เพื่อสร้างความมั่นใจในการจัดสรร และยกเลิกการจัดสรรหน่วยความจำโดยตัวจัดสรรหน่วยความจำประเภทเดียวกัน และกำหนดข้อจำกัดไม่ให้เกินหน่วยความจำที่กำหนด[17]
การใช้งาน
[แก้]เมื่อมีการอินแสตนท์คอนเทนเนอร์มาตราฐานของตัวจัดการหน่วยความจำผ่านทางเทมเพลตอาร์กิวเมนต์ ด้วยค่าเริ่มต้น std::allocator<T>;
[18]
namespace std { template <class T, class Allocator = allocator<T> > class vector; // ...
เหมือนกับทุกๆ C++ คลาสเทมเพลต การอินแสตนท์ของคอนเทนเนอร์ไลบรารีมาตราฐาน จะใช้ความแตกต่างอาร์กิวเมนต์ของตัวจัดสรรหน่วยความจำเป็นตัวแยกแยะประเภทข้อมูล ฟังก์ชันที่คาดว่าจะใช้คืออาร์กิวเมนต์ของ std::vector<int>
ซึ่งจะยอมรับแต่เวคเตอร์ (vector
) ของอินแสตนท์ที่เป็นตัวเริ่มต้นของตัวจัดสรรหน่วยความจำ
การปรับปรุงตัวจัดสรรหน่วยความจำใน C++ 11
[แก้]ในมาตราฐานของ C++ ล่าสุดได้ปรับปรุงตัวจัดสรรหน่วยความจำให้สามารถยอมรับ "ขอบเขต" (scope) ของตัวจัดสรรหน่วยความจำ และคอนเทเนอร์ที่ประกอบด้วยการจัดสรรหน่วยความจำที่ซ้อนกัน (Nested) เช่น เวคเตอร์ของสตริง หรือ แมพ (map) ของลิสท์ ของเซต ของประเภทข้อมูลที่ถูกกำหนดโดยผู้ใช้, สามารถมั่นใจว่าหน่วยความจำทั้งหมดได้มาจากคอนเทนเนอร์ของตัวจัดสรรหน่วยความจำ[19]
อ้างอิง
[แก้]- ↑ Stepanov, Alexander; Meng Lee (7 March 1994). "The Standard Template Library. Presentation to the C++ standards committee". Hewlett Packard Libraries. Retrieved 12 May 2009.
- ↑ 2.0 2.1 2.2 Stevens, Al (1995). "Al Stevens Interviews Alex Stepanov". Dr Dobb's Journal. Archived from the original on 1 May 2009. Retrieved 12 May 2009.
- ↑ 3.0 3.1 3.2 Stroustrup, Bjarne (1997). The C++ Programming Language, 3rd edition. Addison-Wesley.
- ↑ 4.0 4.1 4.2 4.3 4.4 4.5 Meyers, Scott (2001). Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library. Addison-Wesley.
- ↑ Lo Russo, Graziano (1997). "An Interview with A. Stepanov". www.stlport.org. Retrieved 13 May 2009.
- ↑ Halpern, Pablo (4 February 2008). "Allocator-specific Swap and Move Behavior". ISO. Retrieved 21 August 2012.
- ↑ Halpern, Pablo (22 October 2009). "Allocators post Removal of C++ Concepts (Rev 1)". ISO. Retrieved 21 August 2012.
- ↑ Becker, Pete. "LWG Issue 1318: N2982 removes previous allocator capabilities (closed in March, 2011)". ISO. Retrieved 21 August 2012.
- ↑ 9.0 9.1 9.2 ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++§20.1.5 Allocator requirements
- ↑ 10.0 10.1 ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++§20.1.5 Allocator requirements [lib.allocator.requirements] para. 5
- ↑ Langer, Angelika; Klaus Kreft (1998). "Allocator Types". C++ Report. Retrieved 13 May 2009.
- ↑ 12.0 12.1 12.2 Austern, Matthew (1 December 2000). "The Standard Librarian: What Are Allocators Good For?". Dr. Dobb's Journal. Archived from the original on 28 April 2009. Retrieved 12 May 2009.
- ↑ 13.0 13.1 13.2 13.3 Aue, Anthony (1 September 2005). "Improving Performance with Custom Pool Allocators for STL". Dr Dobb's Journal. Retrieved 13 May 2009.
- ↑ ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++§20.4.1.1 allocator members [lib.allocator.members] para. 3
- ↑ 15.0 15.1 15.2 Alexandrescu, Andrei (2001). Modern C++ Design. Addison-Wesley. p. 352.ISBN 0-201-70431-5.
- ↑ Vlasceanu, Christian (1 April 2001). "Debugging Memory Errors with Custom Allocators". Dr Dobb's Journal. Retrieved 14 May 2009.
- ↑ 17.0 17.1 Austern, Matthew (1 December 2001). "The Standard Librarian: A Debugging Allocator". Dr Dobb's Journal. Retrieved 14 May 2009.
- ↑ ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §23.2 Sequences [lib.sequences] para. 1
- ↑ Halpern, Pablo (29 February 2008). "The Scoped Allocator Model (Rev 2)".ISO. Retrieved 21 August 2012.
แหล่งข้อมูลอื่น
[แก้]- CodeGuru Allocators (STL). เก็บถาวร 2014-07-29 ที่ เวย์แบ็กแมชชีน
- An introductory article "C++ Standard Allocator, An Introduction and Implementation".
- A custom allocator implementation based on malloc