Ojective-C Programming – Basic Memory Management

ก็ห่างหายหน้า หายตากันไปกว่าๆ 2 อาทิตย์ที่ไม่ได้เขียน tutorial ก็ติดงานค่อนข้างวุ่นวายทีเดียว ก็พยายามปลีกเวลามาเขียนเพราะหลังๆ เข้าใจว่าหลายคนอยากจะก้าวไปยัง iPhone ใจจริงก็อยากจะขึ้น cocoa + iPhone ใจจะขาด แต่คิดไปคิดมา ยังเหลือเรื่องเกี่ยวกับ objective-c ที่เป็น Fundamental อยู่อีกหลายเรื่อง ก็เลยตัดสินใจว่าจะเขียน ให้มันครอบคลุมในส่วนที่ต้องใช้และเข้าใจก่อนไป สู่การเขียน cocoa และ iPhone เป็นลำดับ

เอาละเข้าสู้เนื้อหากันเลยดีกว่า

Memory Management อาจจะฟังดูน่ากลัวสักหน่อยว่า เราจะต้องเข้าใจในระดับไหน แต่เอาเป็นว่าการจัดการหน่วยความจำ เนี่ยเป็นสิ่งสำคัญมากสำหรับการเขียน โปรแกรม ถ้าเป็นอย่างภาษา java หรือว่า Visual Basic  อาจจะดีหน่อยตรงที่ว่า เราไม่ต้องไปยุ่งเกี่ยวอะไรเกี่ยวกับ memory เลย อยากประกาศก็ตัวแปร ก็ประกาศ ใช้เสร็จก็ช่างมัน อะไรแบบนี้ ก็เนื่องด้วยว่าภาษาเหล่านี้ได้ทำการจัดการหน่วยความจำให้เราโดยอัตโนมัติ เราเลยไม่มีความจำเป็นต้องจัดการเอง ส่วนภาษา Objective-C  นั้นก็มีการจัดการหน่อยความจำให้เหมือนกัน มี garbage collector เช่นกัน แต่มันยืดหยุ่นกว่า ตรงที่ว่า เราสามารถจัดการเองได้ด้วย

Autorelease Pool

การจัดการเกี่ยวกับ memory อย่างแรกเลยที่ต้องรู้ และน่าจะคุ้นเคยก็คือ NSAutoReleasePool ชื่อมันอาจจะเหมือนว่า ทำให้อัตโนมัติแต่ความเป็นจริงแล้วก็ไม่ได้เป็นอย่างที่ว่า ความสำคัญของ class นี้คือ

ถ้า object ได้ส่ง message ให้ทำการ release.
ตัว object นั้นจะถูกใส่เข้าไปยัง pool เพื่อที่ว่า ถ้าเมื่อไหร่ pool ได้คืนหน่วยความจำ ( release ) ให้กับระบบ มันก็จะไปไล่คืนหน่วยความจำให้กับทุกๆ object ที่อยู่ใน pool

ถ้าเราทำการเขียนโปรแกรมด้วย Foundation Framework จะต้องมี Autorelease pool อยู่ด้วยเสมอ ( ถ้าเป็น cocoa เราไม่ต้องประกาศก็ได้ เพราะว่ามันจะมีมาให้อยู่แล้ว )

บางทีก็อาจจะจำเป็นที่จำต้องมีหลายๆ autorelease pool เช่นกรณีที่ว่า โปรแกรม loop ไปนานมากๆ แบบนี้ก็ถ้ามีหลายๆ pool ค่อยๆทยอย release ก็อาจจะดีกว่า เช่นว่า

Retain & Release

เราต้องทำความเข้าใจกันก่อนว่า Object ในโปรแกรมสัก 1 ตัว อาจจะมี Object อื่นๆทำการใช้งานมันอยู่ จะเกิดอะไรเกิดขึ้นถ้าเผื่อว่า ObjectA ต้องการจะเรียกใช้ ObjectB แต่กลายเป็นว่า ObjectB ได้ release ไปแล้ว. แต่โดยความจริงแล้วส่วนมากปัญหามักจะเกิดจากการไม่คืนหน่วยความจำซะมากกว่า.

ในภาษา Objective-C นั้นถ้าหาก Object ใดๆที่มีการถูกใช้งานโดย Object อื่นๆจะไม่สามารถ free memory ได้ จนกว่าจะไม่มี Object ใดๆใช้มันอีก. เอาละปัญหาก็เกิดขึ้นอีก ว่าจะทำอย่างไรให้รู้ว่าไม่มี Object ไหนใช้ ?

ปัญหานี้ก็แก้ได้โดยการบอกกับ object ตัวนั้นให้มันนับว่ามีใครอ้างถึงมันมากเท่าไหร่ สำหรับ function ที่เอาไว้บอกว่า เราได้ทำการใช้มัน อยู่ก็คือ retain .

retain นั้นจะไปเพิ่มจำนวนของ counter ให้กับ object นั้นว่ามีการอ้างถึง
ในทางกลับกัน release ก็จะไปลดจำนวนการอ้างอิง

releaseCount เอาไว้บอกจำนวนของ object ที่มาใช้งานตัวมันอยู่

มาดูตัวอย่างง่ายกันดีกว่า

ก็จากตัวอย่าง ข้างบนอธิบายคร่าวๆก่อนแล้วกัน คือ เราทำการประกาศ ObjectA ขึ้นมาแล้วก็ ประกาศ array มา อีกตัว

ในครั้งแรกหลังจากประกาศเราก็ทำการ นับค่าตัวที่อ้างอิงก็จะได้ผลลัพธ์เป็น 1 เพราะมีแต่ตัวเองใช้

หลังจากนั้น ก็เอา ObjectA ใส่เข้าไปยัง array แล้วนับใหม่ก็ จะได้เป็น 2 เพราะ array ได้อ้างอิงถึง objectA อีกตัว

และก็เรียกใช้ retain เฉยๆ ก็จะเพิ่มเป็น 3

หลังจากนั้นก็เรียก release จำนวนก็ลดลงเหลือ 2 และสุดท้าย

ก็ลบ ObjectA ออกจาก array นับใหม่ก็จะได้ 1 เหมือนเดิม

ผลลัพธ์ที่ได้ก็จะมีหน้าตาประมาณนี้

objectA retain count = 1

objectA after add to Array
retain count = 2

objectB after refer to objectA
retain count = 2

objectA after retain
retain count = 3

objectA after release
retain count = 2

objectA after remove from array
retain count = 1

ก็เป็นว่าน่าจะพอเข้าใจเบื้องต้นเกี่ยวกับ memory management เพิ่มบ้างอ่ะน่ะ

Leave a Reply