ตัวจัดสรรหน่วยความจำ

บทความนี้เป็นบทความแปลของพนักงานดีแทคในความร่วมมือกับวิกิพีเดีย คลิกเพื่อดูข้อมูลเพิ่มเติม
จากวิกิพีเดีย สารานุกรมเสรี

ในการเขียนโปรแกรมคอมพิวเตอร์ภาษาซีพลัสพลัส, 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]

อ้างอิง[แก้]

  1. 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. 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. 3.0 3.1 3.2 Stroustrup, Bjarne (1997). The C++ Programming Language, 3rd edition. Addison-Wesley.
  4. 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.
  5. Lo Russo, Graziano (1997). "An Interview with A. Stepanov". www.stlport.org. Retrieved 13 May 2009.
  6. Halpern, Pablo (4 February 2008). "Allocator-specific Swap and Move Behavior". ISO. Retrieved 21 August 2012.
  7. Halpern, Pablo (22 October 2009). "Allocators post Removal of C++ Concepts (Rev 1)". ISO. Retrieved 21 August 2012.
  8. Becker, Pete. "LWG Issue 1318: N2982 removes previous allocator capabilities (closed in March, 2011)". ISO. Retrieved 21 August 2012.
  9. 9.0 9.1 9.2 ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++§20.1.5 Allocator requirements 
  10. 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
  11. Langer, Angelika; Klaus Kreft (1998). "Allocator Types". C++ Report. Retrieved 13 May 2009.
  12. 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. 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.
  14. ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++§20.4.1.1 allocator members [lib.allocator.members] para. 3
  15. 15.0 15.1 15.2 Alexandrescu, Andrei (2001). Modern C++ Design. Addison-Wesley. p. 352.ISBN 0-201-70431-5.
  16. Vlasceanu, Christian (1 April 2001). "Debugging Memory Errors with Custom Allocators". Dr Dobb's Journal. Retrieved 14 May 2009.
  17. 17.0 17.1 Austern, Matthew (1 December 2001). "The Standard Librarian: A Debugging Allocator". Dr Dobb's Journal. Retrieved 14 May 2009.
  18. ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §23.2 Sequences [lib.sequences] para. 1
  19. Halpern, Pablo (29 February 2008). "The Scoped Allocator Model (Rev 2)".ISO. Retrieved 21 August 2012.

แหล่งข้อมูลอื่น[แก้]