จะเกิดอะไรขึ้นเมื่อคุณไม่ว่างหลังจาก malloc?


538

นี่เป็นสิ่งที่รบกวนฉันมานานแล้ว

เราทุกคนได้รับการสอนในโรงเรียน (อย่างน้อยฉันเป็น) ที่คุณต้องเป็นอิสระทุกตัวชี้ที่ได้รับการจัดสรร แต่ฉันก็อยากรู้อยากเห็นเกี่ยวกับต้นทุนที่แท้จริงของการไม่เพิ่มหน่วยความจำ ในบางกรณีที่เห็นได้ชัดเช่นเมื่อmallocมีการเรียกภายในลูปหรือส่วนหนึ่งของการประมวลผลเธรดเป็นสิ่งสำคัญมากที่จะต้องว่างดังนั้นจึงไม่มีหน่วยความจำรั่วไหล แต่ลองพิจารณาสองตัวอย่างต่อไปนี้:

ก่อนอื่นถ้าฉันมีรหัสนั่นเป็นอย่างนี้:

int main()
{
    char *a = malloc(1024);
    /* Do some arbitrary stuff with 'a' (no alloc functions) */
    return 0;
}

ผลลัพธ์ที่แท้จริงที่นี่คืออะไร ความคิดของฉันคือกระบวนการตายแล้วพื้นที่ฮีปก็หายไปดังนั้นจึงไม่มีอันตรายใด ๆ ในการที่จะพลาดการเรียกfree(แต่ฉันตระหนักถึงความสำคัญของการมีมันต่อไปสำหรับการปิดการบำรุงรักษาและการปฏิบัติที่ดี) ฉันคิดถูกไหม?

ประการที่สองสมมติว่าฉันมีโปรแกรมที่ทำหน้าที่เหมือนเชลล์ ผู้ใช้สามารถประกาศตัวแปรเช่นaaa = 123นั้นและจะถูกเก็บไว้ในโครงสร้างข้อมูลแบบไดนามิกบางอย่างเพื่อใช้ในภายหลัง เห็นได้ชัดว่าดูเหมือนว่าคุณจะใช้วิธีแก้ปัญหาบางอย่างที่จะเรียกใช้ฟังก์ชันการจัดสรร * บางอย่าง (hashmap, รายการที่ลิงก์, สิ่งที่คล้ายกัน) สำหรับโปรแกรมประเภทนี้มันไม่สมเหตุสมผลเลยที่จะโทรฟรีmallocเพราะตัวแปรเหล่านี้จะต้องปรากฏตลอดเวลาในระหว่างการดำเนินการของโปรแกรมและไม่มีวิธีที่ดี (ที่ฉันเห็น) ในการดำเนินการนี้ด้วยการจัดสรรพื้นที่แบบคงที่ เป็นการออกแบบที่ไม่ดีที่จะมีหน่วยความจำจำนวนมากที่จัดสรรไว้ แต่ปล่อยให้เป็นอิสระซึ่งเป็นส่วนหนึ่งของกระบวนการที่สิ้นสุด ถ้าเป็นเช่นนั้นทางเลือกคืออะไร?


7
@NTDLS ความมหัศจรรย์ของระบบการให้คะแนนใช้งานได้จริงครั้งเดียว: 6 ปีและคำตอบที่ "สมควรได้รับมากกว่า" ได้เพิ่มขึ้นอย่างแน่นอน
zxq9

15
คนด้านล่างพูดว่าระบบปฏิบัติการสมัยใหม่ที่ดีจะทำการล้างข้อมูล แต่ถ้ารหัสกำลังทำงานในโหมดเคอร์เนล (เช่นสำหรับเหตุผลด้านประสิทธิภาพ) มีโปรแกรมโหมดเคอร์เนล (ใน Linux เป็นตัวอย่าง) หรือไม่ ถ้าไม่ฉันเชื่อว่าดังนั้นคุณจะต้องปลดปล่อยทุกอย่างด้วยตนเองฉันคิดว่าก่อนที่จะมีการยกเลิกที่ผิดปกติเช่นเดียวกับแท้ง ()
Dr. Person Person II

3
@ Dr.PersonPersonII ใช่แล้วรหัสที่ใช้ในโหมดเคอร์เนลมักจะมีการปล่อยทุกอย่างด้วยตนเอง
zwol

1
ฉันต้องการเพิ่มที่free(a)ไม่ได้ทำอะไรเพื่อเพิ่มความจำจริง ๆ ! มันรีเซ็ตตัวชี้บางอย่างในการใช้งาน libc ของ malloc ซึ่งติดตามหน่วยความจำที่มีอยู่ภายในหน้าหน่วยความจำขนาดใหญ่ที่มีการแมปขนาดใหญ่ (ปกติเรียกว่า "ฮีป") หน้านั้นจะยังคงเป็นอิสระเมื่อโปรแกรมของคุณสิ้นสุดลงก่อนหน้านี้เท่านั้น
Marco Bonelli

1
ว่าง () อาจหรือไม่จริงปล่อยหน่วยความจำ มันอาจทำเครื่องหมายบล็อกว่าเป็นอิสระเพื่อนำมาใช้ใหม่ในภายหลังหรืออาจลิงก์ไปยังรายการอิสระ มันอาจรวมเข้าไปในบล็อกว่างที่อยู่ติดกันหรืออาจปล่อยให้การจัดสรรภายหลังทำ มันคือรายละเอียดการติดตั้งทั้งหมด
Jordan Brown

คำตอบ:


378

เกือบทุกระบบปฏิบัติการที่ทันสมัยจะกู้คืนพื้นที่หน่วยความจำที่จัดสรรไว้ทั้งหมดหลังจากที่โปรแกรมออก ข้อยกเว้นเดียวที่ฉันคิดได้อาจเป็นสิ่งที่คล้ายกับ Palm OS ซึ่งเป็นที่เก็บข้อมูลแบบคงที่ของโปรแกรมและหน่วยความจำรันไทม์ค่อนข้างเหมือนกันดังนั้นการไม่ปล่อยอาจทำให้โปรแกรมใช้พื้นที่เก็บข้อมูลเพิ่มขึ้น (ฉันแค่คาดเดาที่นี่เท่านั้น)

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

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

ในทางตรงกันข้ามคำเตือนที่คล้ายกันเพื่อปิดไฟล์ของคุณเมื่อออกมีผลเป็นรูปธรรมมากขึ้น - ถ้าคุณทำไม่ได้ข้อมูลที่คุณเขียนถึงพวกเขาอาจไม่ได้รับการล้างหรือถ้าพวกเขาเป็นไฟล์ชั่วคราวพวกเขาอาจไม่ ถูกลบเมื่อเสร็จแล้ว นอกจากนี้การจัดการฐานข้อมูลควรมีการทำธุรกรรมของพวกเขาแล้วปิดเมื่อคุณทำกับพวกเขา ในทำนองเดียวกันถ้าคุณใช้ภาษาเชิงวัตถุเช่น C ++ หรือ Objective C การไม่ปล่อยวัตถุเมื่อเสร็จแล้วจะหมายถึงว่าตัวทำลายจะไม่ถูกเรียกใช้และทรัพยากรใด ๆ ที่ชั้นเรียนรับผิดชอบอาจไม่ได้รับการทำความสะอาด


16
อาจเป็นเรื่องดีที่จะกล่าวถึงว่าทุกคนไม่ได้ใช้ระบบปฏิบัติการที่ทันสมัยถ้ามีคนใช้โปรแกรมของคุณ (และยังคงทำงานบนระบบปฏิบัติการที่ไม่ได้กู้คืนหน่วยความจำ) เรียกใช้ GG
user105033

79
ฉันพิจารณาคำตอบนี้ผิดจริง ๆ เราควรจัดสรรคืนทรัพยากรเสมอหลังจากทำเสร็จแล้วไม่ว่าจะเป็นไฟล์ที่จัดการ / หน่วยความจำ / mutex เมื่อมีนิสัยเช่นนี้เราจะไม่ทำผิดพลาดแบบนั้นเมื่อสร้างเซิร์ฟเวอร์ เซิร์ฟเวอร์บางตัวคาดว่าจะเรียกใช้ 24x7 ในกรณีดังกล่าวการรั่วไหลของการเรียงลำดับใด ๆ หมายความว่าเซิร์ฟเวอร์ของคุณจะหมดทรัพยากรในที่สุดและหยุด / หยุดทำงานในบางวิธี โปรแกรมอรรถประโยชน์แบบสั้น ๆ การรั่วไหลนั้นไม่เลวเลย เซิร์ฟเวอร์ใด ๆ การรั่วไหลใด ๆ ก็คือความตาย ทำตัวเองชอบ ทำความสะอาดตัวเอง มันเป็นนิสัยที่ดี
EvilTeach

120
ส่วนใดของ "อย่างไรก็ตามถือว่าเป็นสไตล์ที่ดีในการเพิ่มหน่วยความจำทันทีที่คุณไม่ต้องการมันอีกต่อไปและเพื่อปลดปล่อยทุกสิ่งที่คุณยังมีอยู่เมื่อออกจากโปรแกรม" คุณคิดว่าผิดหรือเปล่า?
Paul Tomblin

24
หากคุณมีที่เก็บหน่วยความจำที่คุณต้องการจนถึงตอนที่โปรแกรมออกและคุณไม่ได้ทำงานบนระบบปฏิบัติการดั้งเดิมจากนั้นการเพิ่มหน่วยความจำก่อนที่คุณจะออกจะเป็นตัวเลือกสำนวนไม่ใช่ข้อบกพร่อง
Paul Tomblin

30
@Paul - เพียงแค่เห็นด้วยกับ EvilTeach ไม่ถือว่าเป็นรูปแบบที่ดีในการเพิ่มหน่วยความจำมันไม่ถูกต้องที่จะไม่เพิ่มหน่วยความจำ ข้อความของคุณทำให้สิ่งนี้ดูมีความสำคัญเท่ากับการใส่ผ้าเช็ดหน้าที่เข้ากับเน็คไทของคุณ จริงๆแล้วมันเป็นระดับของการสวมใส่กางเกง
Heath Hunnicutt

110

ใช่คุณถูกตัวอย่างของคุณจะไม่ทำอันตรายใด ๆ (อย่างน้อยไม่ได้อยู่ในระบบปฏิบัติการที่ทันสมัยที่สุด) หน่วยความจำทั้งหมดที่จัดสรรโดยกระบวนการของคุณจะถูกกู้คืนโดยระบบปฏิบัติการเมื่อกระบวนการออก

ที่มา: การจัดสรรและ GC Myths (การแจ้งเตือน PostScript!)

การจัดสรรตำนาน 4: โปรแกรมที่ไม่ได้เก็บขยะควรทำการจัดสรรคืนหน่วยความจำทั้งหมดที่จัดสรร

ความจริง: การยกเลิกการจัดสรรในรหัสที่ดำเนินการบ่อยครั้งทำให้เกิดการรั่วไหลเพิ่มขึ้น พวกเขาไม่ค่อยได้รับการยอมรับ แต่โปรแกรมที่เก็บรักษาหน่วยความจำส่วนใหญ่ที่จัดสรรไว้จนกว่าโปรแกรมจะออกมักจะทำงานได้ดีขึ้นโดยไม่ต้องทำการจัดสรรคืน Malloc นั้นง่ายต่อการติดตั้งหากไม่มีให้ฟรี

ในกรณีส่วนใหญ่การจัดสรรคืนหน่วยความจำก่อนออกจากโปรแกรมจะไม่มีจุดหมาย ระบบปฏิบัติการจะเรียกคืนมันต่อไป ฟรีจะสัมผัสและหน้าในวัตถุที่ตายแล้ว ระบบปฏิบัติการจะไม่

ผลที่ตามมา: ระวังด้วย "เครื่องตรวจจับการรั่วไหล" ที่นับการจัดสรร "การรั่วไหล" บางอย่างดี!

ที่กล่าวว่าคุณควรพยายามหลีกเลี่ยงการรั่วไหลของหน่วยความจำทั้งหมด!

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


3
อาจเป็นเพราะคำถามที่ฉันอ่านมันเป็นสิ่งที่เกิดขึ้นจริงกับหน่วยความจำรั่วไม่ว่าตัวอย่างเฉพาะนี้ไม่เป็นไร ฉันไม่ยอมลงคะแนนเพราะมันเป็นคำตอบที่ดี
DevinB

3
อาจเป็นไปได้ว่ามี (Windows รุ่นแรก ๆ , Mac OS ต้น) และอาจจะยังคงเป็น OS ที่ต้องใช้กระบวนการในการเพิ่มหน่วยความจำก่อนออกมิฉะนั้นพื้นที่จะไม่ถูกเรียกคืน
Pete Kirkham

ไม่เป็นไรอย่างสมบูรณ์ถ้าคุณไม่สนใจเรื่องการกระจายตัวของหน่วยความจำหรือหน่วยความจำไม่เพียงพอ - คุณทำสิ่งนี้มากเกินไปและประสิทธิภาพการใช้งานของคุณจะหายไป นอกจากข้อเท็จจริงที่ยากแล้วให้ทำตามแนวปฏิบัติที่ดีที่สุดและสร้างนิสัยที่ดี
NTDLS

1
ฉันมีคำตอบที่ได้รับการยอมรับซึ่งกำลังนั่งประมาณ -11 ดังนั้นเขาจึงไม่แม้แต่จะวิ่งเพื่อบันทึก
Paul Tomblin

8
ฉันคิดว่ามันผิดที่จะอธิบายความจำเป็นในการฟรี () 'กำลังหน่วยความจำโดยการพูดว่า "เพราะเครื่องตรวจจับการรั่วไหล" นี่ก็เหมือนกับการพูดว่า "คุณต้องขับรถช้าๆในสถานที่เล่นเพราะตำรวจอาจรอคุณด้วยกล้องจับความเร็ว"
เซบาสเตียนมัค

57

=== แล้วการพิสูจน์อักษรในอนาคตและการนำรหัสกลับมาใช้ใหม่อย่างไร ===

หากคุณไม่ได้เขียนรหัสเพื่อเพิ่มวัตถุคุณจะ จำกัด รหัสให้ปลอดภัยเมื่อคุณสามารถพึ่งพาหน่วยความจำที่ว่างเมื่อกระบวนการถูกปิด ... เช่นใช้เพียงครั้งเดียวขนาดเล็ก โปรเจ็กต์หรือ "โยนทิ้ง" [1]โปรเจ็กต์) ... ที่ที่คุณรู้ว่าเมื่อไรกระบวนการจะสิ้นสุด

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


[1] เกี่ยวกับโครงการ "ทิ้งห่าง" รหัสที่ใช้ในโครงการ "โยนทิ้ง" มีวิธีที่จะไม่ถูกโยนทิ้งไป สิ่งต่อไปที่คุณรู้ว่าผ่านไปสิบปีแล้วและยังคงใช้รหัส "ทิ้ง" อยู่)

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


8
ลงคะแนนสำหรับ "โครงการขนาดเล็ก" มีหลายโครงการขนาดใหญ่ที่จงใจไม่เพิ่มหน่วยความจำเมื่อออกเพราะมันเสียเวลาถ้าคุณรู้ว่าแพลตฟอร์มเป้าหมายของคุณ IMO ตัวอย่างที่แม่นยำยิ่งขึ้นน่าจะเป็น "โครงการแยก" เช่นถ้าคุณกำลังสร้างไลบรารี่ที่ใช้ซ้ำได้ซึ่งจะรวมอยู่ในแอพพลิเคชั่นอื่น ๆ ก็จะไม่มีจุดออกที่กำหนดไว้อย่างชัดเจนดังนั้นคุณจึงไม่ควรปล่อยให้หน่วยความจำรั่ว สำหรับแอปพลิเคชันแบบสแตนด์อโลนคุณจะรู้ได้อย่างแน่นอนเสมอว่ากระบวนการจะสิ้นสุดเมื่อใดและสามารถตัดสินใจอย่างมีสติในการลดการล้างข้อมูลลงในระบบปฏิบัติการ (ซึ่งต้องทำการตรวจสอบด้วยวิธีใดวิธีหนึ่ง)
Dan Bechard

แอปพลิเคชั่นของเมื่อวานคือฟังก์ชั่นห้องสมุดของวันนี้และพรุ่งนี้จะเชื่อมโยงกับเซิร์ฟเวอร์ที่มีอายุการใช้งานนานนับพัน
Adrian McCarthy

1
@AdrianMcCarthy: หากฟังก์ชั่นตรวจสอบว่าตัวชี้คงที่เป็นโมฆะเริ่มต้นด้วยmalloc()ถ้ามันเป็นและยุติถ้าตัวชี้ยังคงเป็นโมฆะฟังก์ชั่นดังกล่าวอาจถูกใช้อย่างปลอดภัยจำนวนครั้งแม้ว่าfreeจะไม่เคยเรียก ฉันคิดว่ามันคงคุ้มค่าที่จะแยกการรั่วไหลของหน่วยความจำซึ่งสามารถใช้พื้นที่เก็บข้อมูลได้ไม่ จำกัด จำนวนมากเมื่อเทียบกับสถานการณ์ที่สามารถสูญเสียพื้นที่เก็บข้อมูลที่ จำกัด และคาดการณ์ได้เท่านั้น
supercat

@supercat: ความคิดเห็นของฉันพูดถึงการเปลี่ยนรหัสเมื่อเวลาผ่านไป แน่นอนว่าการรั่วไหลของจำนวนหน่วยความจำที่มีขอบเขตไม่มีปัญหา แต่สักวันใครบางคนอยากเปลี่ยนฟังก์ชั่นนั้นเพื่อไม่ให้ใช้ตัวชี้คงที่อีกต่อไป หากรหัสไม่มีข้อกำหนดสำหรับความสามารถในการปล่อยหน่วยความจำแบบชี้ไปที่นั่นจะเป็นการเปลี่ยนแปลงที่ยาก (หรือแย่กว่านั้นคือการเปลี่ยนแปลงจะไม่ดีและคุณจะสิ้นสุดด้วยการรั่วไหลที่ไม่มีขอบเขต)
Adrian McCarthy

1
@AdrianMcCarthy: การเปลี่ยนรหัสเป็นไม่ใช้ตัวชี้แบบคงที่อาจต้องย้ายตัวชี้ไปยังวัตถุ "บริบท" บางชนิดและเพิ่มรหัสเพื่อสร้างและทำลายวัตถุดังกล่าว หากตัวชี้อยู่เสมอnullหากไม่มีการจัดสรรและไม่ใช่ค่าว่างเมื่อมีการจัดสรรให้มีรหัสฟรีการจัดสรรและตั้งค่าตัวชี้เป็นnullเมื่อบริบทถูกทำลายจะตรงไปตรงมาโดยเฉพาะอย่างยิ่งเมื่อเทียบกับทุกอย่างที่จะต้องทำ เพื่อย้ายวัตถุคงที่ในโครงสร้างบริบท
supercat

52

คุณถูกต้องไม่มีอันตรายใด ๆ และเร็วกว่าที่จะออก

มีสาเหตุหลายประการสำหรับสิ่งนี้:

  • สภาพแวดล้อมเดสก์ทอปและเซิร์ฟเวอร์ทั้งหมดเพียงแค่ปล่อยพื้นที่หน่วยความจำทั้งหมดเมื่อออก () พวกเขาไม่รู้จักโครงสร้างข้อมูลภายในโปรแกรมเช่นฮีป

  • free()การใช้งานเกือบทั้งหมดไม่ได้ส่งคืนหน่วยความจำไปยังระบบปฏิบัติการอยู่ดี

  • ที่สำคัญกว่านั้นคือเสียเวลาเมื่อทำเสร็จก่อนออก () เมื่อออกหน้าหน่วยความจำและพื้นที่สว็อปจะถูกปล่อยออกมาอย่างง่ายดาย ในทางตรงกันข้ามชุดโทรฟรี () จะเผาไหม้เวลา CPU และอาจส่งผลให้การดำเนินการเพจเพจแคชที่ไม่ได้รับและการขับแคช

เกี่ยวกับpossiblilityรหัสอนาคตที่นำมาใช้ justifing ความเชื่อมั่นของ Ops ไม่มีจุดหมาย: ที่พิจารณา แต่มันก็เป็นเนื้อหาที่ไม่เปรียววิธี YAGNI!


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

3
ใจไม่เคยได้พบคำตอบ: stackoverflow.com/questions/1421491/... ขอบคุณเช่นกัน!
user106740

@aviggiano ที่เรียกว่า YAGNI
v.oddou

หลักการ YAGNI ทำงานได้ทั้งสองวิธี: คุณไม่จำเป็นต้องปรับเส้นทางการปิดระบบให้เหมาะสม การเพิ่มประสิทธิภาพก่อนวัยและทุกสิ่งที่
Adrian McCarthy

26

ฉันไม่เห็นด้วยกับทุกคนที่บอกว่า OP ถูกต้องหรือไม่มีอันตรายใด ๆ

ทุกคนกำลังพูดถึงระบบปฏิบัติการที่ทันสมัยและ / หรือดั้งเดิม

แต่ถ้าฉันอยู่ในสภาพแวดล้อมที่ฉันไม่มีระบบปฏิบัติการอยู่ล่ะ ไม่มีที่ไหนเลย

ลองนึกภาพตอนนี้คุณกำลังใช้อินเตอร์รัปต์การจัดรูปแบบเธรดและจัดสรรหน่วยความจำ ในมาตรฐาน C ISO / IEC: 9899 อายุการใช้งานของหน่วยความจำที่ระบุไว้เป็น:

7.20.3 ฟังก์ชั่นการจัดการหน่วยความจำ

1 ลำดับและที่อยู่ติดกันของหน่วยเก็บที่จัดสรรโดยการเรียกไปยังฟังก์ชัน calloc, malloc และ realloc ที่ต่อเนื่องกันนั้นไม่ได้ระบุไว้ ตัวชี้ส่งคืนถ้าการจัดสรรสำเร็จถูกจัดตำแหน่งอย่างเหมาะสมเพื่อให้สามารถกำหนดให้ตัวชี้ไปยังวัตถุชนิดใดก็ได้จากนั้นใช้เพื่อเข้าถึงวัตถุหรืออาร์เรย์ของวัตถุดังกล่าวในพื้นที่ที่จัดสรร (จนกว่าจะมีการจัดสรรพื้นที่อย่างชัดเจน) . อายุการใช้งานของออบเจ็กต์ที่จัดสรรจะขยายจากการจัดสรรจนถึงการยกเลิกการจัดสรร [... ]

ดังนั้นจึงไม่ควรที่จะระบุว่าสภาพแวดล้อมกำลังทำงานให้คุณ มิฉะนั้นจะถูกเพิ่มเข้าไปในประโยคสุดท้าย: "หรือจนกว่าโปรแกรมจะสิ้นสุด"

ดังนั้นในคำอื่น ๆ : ไม่พ้นความจำไม่ได้เป็นเพียงการปฏิบัติที่ไม่ดี มันผลิตไม่พกพาและไม่ได้มาตรฐานรหัส C ซึ่งอย่างน้อยสามารถเห็นได้ว่า 'ถูกต้องหากต่อไปนี้: [... ], ได้รับการสนับสนุนจากสภาพแวดล้อม'

แต่ในกรณีที่คุณไม่มี OS เลยไม่มีใครทำงานให้คุณ (ฉันรู้ว่าโดยทั่วไปคุณไม่ได้จัดสรรและจัดสรรหน่วยความจำบนระบบฝังตัว แต่มีบางกรณีที่คุณอาจต้องการ)

ดังนั้นในการพูดทั่วไปทั่วไป C (ซึ่งติดแท็ก OP) นี่เป็นเพียงการสร้างรหัสที่ผิดพลาดและไม่พกพาได้


4
ข้อโต้แย้งคือถ้าคุณเป็นสภาพแวดล้อมแบบฝังตัวคุณ - ในฐานะนักพัฒนาจะต้องพิถีพิถันในการจัดการหน่วยความจำตั้งแต่แรก โดยทั่วไปนี่เป็นจุดที่จริงแล้วการจัดสรรหน่วยความจำคงที่ล่วงหน้าไว้ล่วงหน้าแทนที่จะมีรันไทม์ mallocs / reallocs เลย
John Go-Soco

1
@lunarplasma: ในขณะที่สิ่งที่คุณพูดนั้นไม่ถูกต้อง แต่นั่นก็ไม่ได้เปลี่ยนความจริงที่ว่ามาตรฐานภาษาระบุไว้และใครก็ตามที่ต่อต้าน / เพิ่มเติมอาจเป็นไปได้ที่สามัญสำนึกกำลังสร้างรหัสที่ จำกัด ฉันสามารถเข้าใจได้ถ้ามีคนบอกว่า "ฉันไม่ต้องสนใจมัน" เพราะมีหลายกรณีที่พอใช้ได้ แต่อย่างน้อยก็ควรรู้ว่าทำไมเขาไม่ต้องสนใจ และโดยเฉพาะอย่างยิ่งไม่ละเว้นมันตราบใดที่คำถามไม่เกี่ยวข้องกับกรณีพิเศษนั้น และเนื่องจาก OP กำลังถามเกี่ยวกับ C โดยทั่วไปภายใต้แง่มุมทางทฤษฎี (โรงเรียน) ไม่ควรที่จะพูดว่า "คุณไม่จำเป็นต้อง"!
dhein

2
ในสภาพแวดล้อมส่วนใหญ่ที่ไม่มีระบบปฏิบัติการจะไม่มีทางที่โปรแกรมสามารถ "ยุติ"
supercat

@supercat: ตามที่ฉันได้เขียนไว้ก่อนหน้า: คุณพูดถูก แต่ถ้ามีใครซักคนถามเกี่ยวกับเหตุผลในการสอนและแง่มุมของโรงเรียนมันไม่ถูกต้องที่จะพูดว่า "คุณไม่จำเป็นต้องคิดเกี่ยวกับมันซะส่วนใหญ่เวลามันไม่สำคัญ" ถ้อยคำและพฤติกรรมของภาษา คำจำกัดความให้เหตุผลและเนื่องจากสภาพแวดล้อมส่วนใหญ่จัดการกับคุณคุณไม่สามารถพูดได้ว่าไม่จำเป็นต้องสนใจ นั่นคือจุดของฉัน
dhein

2
-1 สำหรับการอ้างอิงมาตรฐาน C ในขณะที่ส่วนใหญ่ไม่ได้นำมาใช้ในกรณีที่ไม่มีระบบปฏิบัติการเนื่องจากไม่มีรันไทม์ที่จะให้คุณสมบัติมาตรฐานเอกสารโดยเฉพาะอย่างยิ่งเกี่ยวกับการจัดการหน่วยความจำและฟังก์ชั่นห้องสมุดมาตรฐาน พร้อมกับรันไทม์ / OS)

23

ฉันมักจะว่างทุกบล็อคที่จัดสรรเมื่อฉันแน่ใจว่าฉันทำเสร็จแล้ว วันนี้จุดเริ่มต้นของโปรแกรมของฉันอาจเป็นไปได้main(int argc, char *argv[])แต่พรุ่งนี้อาจเป็นfoo_entry_point(char **args, struct foo *f)และพิมพ์เป็นตัวชี้ฟังก์ชัน

ดังนั้นถ้าเกิดว่าตอนนี้ฉันมีรอยรั่ว

เกี่ยวกับคำถามที่สองของคุณหากโปรแกรมของฉันป้อนข้อมูลเป็น = 5 ฉันจะจัดสรรพื้นที่สำหรับหรือจัดสรรพื้นที่เดิมอีกครั้งใน a = "foo" ที่ตามมา สิ่งนี้จะคงอยู่จนกระทั่ง:

  1. ผู้ใช้พิมพ์ 'unset a'
  2. มีการป้อนฟังก์ชันการล้างข้อมูลของฉันไม่ว่าจะเป็นการให้บริการสัญญาณหรือผู้ใช้ที่พิมพ์ 'ออกจาก'

ฉันไม่สามารถนึกถึงระบบปฏิบัติการสมัยใหม่ใด ๆที่ไม่เรียกคืนหน่วยความจำหลังจากกระบวนการออกไป จากนั้นอีกครั้งฟรี () ราคาถูกทำไมไม่ล้างออก อย่างที่คนอื่น ๆ พูดกันเครื่องมืออย่าง valgrind นั้นยอดเยี่ยมสำหรับการมองเห็นรอยรั่วที่คุณไม่ต้องกังวล แม้ว่าบล็อกที่คุณยกตัวอย่างจะมีป้ายกำกับว่า 'ยังเข้าถึงได้' แต่เป็นเสียงรบกวนพิเศษในเอาต์พุตเมื่อคุณพยายามทำให้แน่ใจว่าคุณไม่มีรอยรั่ว

ตำนานอีกเรื่องคือ " ถ้าเป็นหลัก () ฉันไม่ต้องปล่อยให้เป็นอิสระ " นี่ไม่ถูกต้อง พิจารณาสิ่งต่อไปนี้:

char *t;

for (i=0; i < 255; i++) {
    t = strdup(foo->name);
    let_strtok_eat_away_at(t);
}

หากสิ่งนั้นมาก่อนการฟอร์ก / daemonizing (และในทางทฤษฎีทำงานตลอดไป) โปรแกรมของคุณเพิ่งรั่วขนาดที่ไม่ทราบแน่ชัดถึง 255 ครั้ง

โปรแกรมที่ดีเขียนได้ดีควรทำความสะอาดตัวเองเสมอ เพิ่มหน่วยความจำทั้งหมด, ล้างไฟล์ทั้งหมด, ปิด descriptors ทั้งหมด, ยกเลิกการเชื่อมโยงไฟล์ชั่วคราวทั้งหมด, ฯลฯ . ฟังก์ชั่นการล้างข้อมูลนี้ควรจะมาถึงเมื่อสิ้นสุดการทำงานปกติ, หรือเมื่อได้รับสัญญาณร้ายแรงหลายชนิดยกเว้นว่าคุณต้องการออกจากไฟล์บางไฟล์ ตรวจพบความผิดพลาดและดำเนินการต่อ

จริงๆโปรดเป็นคนจิตใจที่น่าสงสารที่ต้องรักษาสิ่งของของคุณเมื่อคุณไปยังสิ่งอื่น ๆ .. มอบให้พวกเขา 'valgrind สะอาด' :)


1
และใช่ฉันเคยมีเพื่อนร่วมทีมบอกฉันว่า: "ฉันไม่จำเป็นต้องโทรฟรี () ใน main ()" <shudders>
Tim Post

free() is cheapนอกเสียจากคุณจะมีโครงสร้างข้อมูลเป็นพันล้านที่มีความสัมพันธ์ที่ซับซ้อนที่คุณต้องปล่อยทีละตัวการสำรวจโครงสร้างข้อมูลเพื่อพยายามที่จะปล่อยทุกอย่างอาจจบลงอย่างมีนัยสำคัญเพิ่มเวลาการปิดระบบของคุณโดยเฉพาะถ้าครึ่งหนึ่งของโครงสร้างข้อมูลนั้น ไปยังดิสก์โดยไม่มีประโยชน์ใด ๆ
โกหก Ryan

3
@LieRyan หากคุณมีพันล้านในขณะที่แท้จริงพันล้านโครงสร้างคุณมากที่สุดเด็ดมีปัญหาอื่น ๆ ที่จำเป็นต้องมีการศึกษาระดับปริญญาเฉพาะของการพิจารณา - วิธีที่เกินขอบเขตของคำตอบนี้โดยเฉพาะ :)
ทิมโพสต์

13

เป็นการดีถ้าคุณออกจากหน่วยความจำโดยไม่เห็นด้วย malloc () จัดสรรหน่วยความจำจากพื้นที่หน่วยความจำที่เรียกว่า "the heap" และฮีปที่สมบูรณ์ของกระบวนการจะถูกปล่อยให้เป็นอิสระเมื่อกระบวนการออกจาก

เหตุผลหนึ่งที่คนยังยืนยันว่ามันเป็นเรื่องดีที่จะปล่อยทุกอย่างก่อนออกจากที่นั่นคือ debuggers หน่วยความจำ (เช่น valgrind บน Linux) ตรวจจับบล็อกที่ไม่เห็นด้วยเป็นหน่วยความจำรั่วและถ้าคุณมีการรั่วไหลของหน่วยความจำ จะตรวจพบได้ยากขึ้นถ้าคุณได้ผลลัพธ์ที่ "ปลอม" ในตอนท้าย


1
Valgrind ทำหน้าที่ค่อนข้างดีในการแยกแยะระหว่าง "leaked" และ "ยังเข้าถึงได้" หรือไม่?
Christoffer

11
-1 สำหรับ "สมบูรณ์ดี" มันเป็นวิธีการเขียนโปรแกรมที่ไม่ดีที่จะออกจากหน่วยความจำที่จัดสรรโดยไม่ต้องปลดปล่อยมัน หากรหัสนั้นถูกแยกเข้าไปในห้องสมุดแล้วมันจะทำให้ memleaks ทั่วทุกสถานที่
DevinB

5
+1 เพื่อชดเชย ดูคำตอบของ compie freeในexitเวลาที่ถือว่าเป็นอันตราย
. GitHub หยุดช่วยน้ำแข็ง

11

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

แก้ไข: มันไม่ถูกต้อง 100% ที่จะกล่าวว่าโปรแกรมที่รันอยู่อื่นถูก จำกัด หน่วยความจำนั้น ระบบปฏิบัติการสามารถให้พวกเขาใช้ค่าใช้จ่ายในการเปลี่ยนโปรแกรมของคุณให้เป็นหน่วยความจำเสมือน ( </handwaving>) อย่างไรก็ตามประเด็นคือถ้าโปรแกรมของคุณเพิ่มหน่วยความจำที่ไม่ได้ใช้งานการเปลี่ยนหน่วยความจำเสมือนมีความจำเป็นน้อยกว่า


11

รหัสนี้จะใช้งานได้ปกติ แต่พิจารณาปัญหาของการใช้รหัสซ้ำ

คุณอาจเขียนโค้ดบางส่วนที่ไม่ได้เพิ่มหน่วยความจำที่จัดสรรไว้มันจะทำงานในลักษณะที่หน่วยความจำจะถูกเรียกคืนโดยอัตโนมัติ ดูเหมือนจะเป็นไร

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

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


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

7

ผลลัพธ์ที่แท้จริงที่นี่คืออะไร

โปรแกรมของคุณรั่วไหลออกมาจากหน่วยความจำ อาจกู้คืนได้ขึ้นอยู่กับระบบปฏิบัติการของคุณ

ระบบปฏิบัติการเดสก์ท็อปที่ทันสมัยส่วนใหญ่ทำการกู้คืนหน่วยความจำ leaked เมื่อกระบวนการสิ้นสุดทำให้เป็นเรื่องเศร้าที่จะไม่สนใจปัญหาดังที่เห็นได้จากคำตอบอื่น ๆ อีกมากมายที่นี่)

แต่คุณจะอาศัยคุณลักษณะด้านความปลอดภัยที่คุณไม่ควรพึ่งพาและโปรแกรมของคุณ (หรือฟังก์ชั่น) อาจจะทำงานในระบบที่พฤติกรรมนี้ไม่ส่งผลในการ "ยาก" หน่วยความจำรั่วไหลต่อไปเวลา

คุณอาจกำลังทำงานในโหมดเคอร์เนลหรือในระบบปฏิบัติการวินเทจ / ฝังตัวซึ่งไม่ได้ใช้การป้องกันหน่วยความจำเป็นการแลกเปลี่ยน (MMUs ใช้พื้นที่ว่างการป้องกันหน่วยความจำมีค่าใช้จ่ายรอบ CPU เพิ่มเติมและไม่มากเกินไปที่จะขอจากโปรแกรมเมอร์เพื่อล้างข้อมูลหลังจากตัวเอง)

คุณสามารถใช้และนำหน่วยความจำกลับมาใช้ใหม่ได้ตามที่คุณต้องการ แต่ให้แน่ใจว่าคุณจัดสรรคืนทรัพยากรทั้งหมดก่อนที่จะออก


5

จริงๆแล้วมันมีส่วนหนึ่งในหนังสือเรียนออนไลน์OSTEPสำหรับหลักสูตรระดับปริญญาตรีในระบบปฏิบัติการซึ่งกล่าวถึงคำถามของคุณอย่างแน่นอน

ส่วนที่เกี่ยวข้องคือ "Forgetting To Free Memory" ในบท Memory APIหน้า 6 ซึ่งให้คำอธิบายต่อไปนี้:

ในบางกรณีอาจดูเหมือนว่าการโทรฟรี () นั้นสมเหตุสมผล ตัวอย่างเช่นโปรแกรมของคุณมีอายุสั้นและจะออกในไม่ช้า ในกรณีนี้เมื่อกระบวนการตายระบบปฏิบัติการจะล้างข้อมูลหน้าที่จัดสรรไว้ทั้งหมดและจะไม่มีหน่วยความจำรั่วไหลเกิดขึ้น แม้ว่าสิ่งนี้จะ“ ทำงาน” อย่างแน่นอน (ดูด้านนอกในหน้า 7) มันอาจเป็นนิสัยที่ไม่ดีในการพัฒนาดังนั้นโปรดระมัดระวังในการเลือกกลยุทธ์ดังกล่าว

ข้อความที่ตัดตอนมานี้อยู่ในบริบทของการแนะนำแนวคิดของหน่วยความจำเสมือน โดยทั่วไป ณ จุดนี้ในหนังสือผู้เขียนอธิบายว่าหนึ่งในเป้าหมายของระบบปฏิบัติการคือ "virtualize memory" นั่นคือเพื่อให้ทุกโปรแกรมเชื่อว่ามันมีการเข้าถึงพื้นที่ที่อยู่หน่วยความจำขนาดใหญ่มาก

เบื้องหลังระบบปฏิบัติการจะแปล "ที่อยู่เสมือน" ที่ผู้ใช้เห็นไปยังที่อยู่จริงที่ชี้ไปยังหน่วยความจำกายภาพ

อย่างไรก็ตามการแบ่งปันทรัพยากรเช่นหน่วยความจำกายภาพต้องใช้ระบบปฏิบัติการเพื่อติดตามกระบวนการที่กำลังใช้อยู่ ดังนั้นหากกระบวนการยกเลิกดังนั้นจึงเป็นความสามารถและเป้าหมายการออกแบบของระบบปฏิบัติการเพื่อเรียกคืนหน่วยความจำของกระบวนการเพื่อให้สามารถแจกจ่ายและแบ่งปันหน่วยความจำกับกระบวนการอื่นได้


แก้ไข:ส่วนที่กล่าวถึงในข้อความที่ตัดตอนมาจะถูกคัดลอกด้านล่าง

ช่วยเหลือ: ทำไมไม่มีหน่วยความจำรั่วไหลออกมาเมื่อกระบวนการของคุณออก

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

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

จากหน้า 7 ของMemory APIบทที่

ระบบปฏิบัติการ: สามชิ้นง่าย ๆ
Remzi H. Arpaci-Dusseau และ Andrea C. Arpaci-Dusseau หนังสือ Arpaci-Dusseau มีนาคม, 2015 (เวอร์ชั่น 0.90)


4

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

หากกระบวนการมีอายุสั้นคุณสามารถหลีกเลี่ยงการทำเช่นนี้ได้เนื่องจากระบบปฏิบัติการจะเรียกคืนหน่วยความจำที่จัดสรรไว้ทั้งหมดเมื่อกระบวนการเสร็จสมบูรณ์


1
ฉันต้องการพูด -1 สำหรับคำสั่งแรกของคุณ "ไม่มีอันตราย" ยกเว้นว่าคุณจะให้คำตอบอย่างรอบคอบเกี่ยวกับสาเหตุที่มีอันตราย
DevinB

2
อันตรายที่เกิดขึ้นมันเป็นสิ่งที่ค่อนข้างใจดี - ฉันจะใช้เวลาหนึ่งวันในการรั่วไหลของหน่วยความจำ
Kyle Cronin

1
จริงมากและเราทั้งคู่ก็ไม่ต้องการ = D
DevinB

2
@KyleCronin ฉันจะมากค่อนข้างมี segfault กว่าหน่วยความจำรั่วเพราะทั้งสองมีข้อบกพร่องที่ร้ายแรงและ segfaults จะง่ายต่อการตรวจสอบ การรั่วไหลของหน่วยความจำทั้งหมดบ่อยเกินไปจะไม่มีใครสังเกตเห็นหรือไม่ได้รับการแก้ไขเพราะพวกเขา "ค่อนข้างใจดี" แรมของฉันและฉันไม่เห็นด้วยอย่างสุดใจ
Dan Bechard

@Dan ในฐานะนักพัฒนาแน่นอน ในฐานะผู้ใช้ฉันจะทำให้หน่วยความจำรั่ว ฉันอยากมีซอฟต์แวร์ที่ใช้งานได้แม้ว่าจะมีหน่วยความจำรั่วมากกว่าซอฟต์แวร์ที่ไม่มี
Kyle Cronin

3

คุณเป็นคนที่ถูกต้องอย่างแท้จริง ในโปรแกรมเล็ก ๆ น้อย ๆ ที่ตัวแปรต้องมีอยู่จนกว่าโปรแกรมจะตายจะไม่มีประโยชน์อย่างแท้จริงในการจัดสรรหน่วยความจำ

ในความเป็นจริงฉันเคยมีส่วนร่วมในโครงการที่การดำเนินการของโปรแกรมแต่ละครั้งมีความซับซ้อนมาก แต่ค่อนข้างสั้นและการตัดสินใจก็คือการจัดสรรหน่วยความจำและไม่ทำให้โครงการไม่มั่นคงโดยทำผิดพลาดการจัดสรรคืน

ที่ถูกกล่าวว่าในโปรแกรมส่วนใหญ่นี่ไม่ใช่ตัวเลือกจริง ๆ หรืออาจทำให้คุณมีหน่วยความจำไม่เพียงพอ


2

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


2

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

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

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


0

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


-2

ฉันคิดว่าตัวอย่างทั้งสองของคุณเป็นเพียงตัวอย่างเดียว: free()ควรเกิดขึ้นในตอนท้ายของกระบวนการซึ่งในขณะที่คุณชี้ให้เห็นก็ไม่มีประโยชน์ตั้งแต่กระบวนการสิ้นสุดลง

ในตัวอย่างที่สองของคุณความแตกต่างเพียงอย่างเดียวคือคุณอนุญาตจำนวนที่ไม่ได้กำหนดmalloc()ซึ่งอาจทำให้หน่วยความจำใกล้หมด วิธีเดียวที่จะจัดการสถานการณ์คือตรวจสอบรหัสส่งคืนmalloc()และดำเนินการให้สอดคล้อง

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