Go อยู่ภายใต้การรั่วไหลของหน่วยความจำเล็กน้อยเช่นเดียวกับ Java หรือไม่?


91

นี่คือข้อเท็จจริง:

  • ภาษา Go มีคนเก็บขยะ

  • Java มีที่เก็บขยะ

  • โปรแกรม Java จำนวนมากมีการรั่วไหลของหน่วยความจำ (บอบบางหรือไม่)

ดังตัวอย่างโปรแกรม Java ที่มีหน่วยความจำรั่ว (ไม่ใช่สำหรับคนใจร้อนคำถามอาจสั่นคลอนความเชื่อของคุณ) ดูที่นี่เกี่ยวกับโปรแกรม Java เล็ก ๆ ที่เรียกว่า Tomcat ที่มีปุ่ม "find leaks": มีวิธี เพื่อหลีกเลี่ยงการรั่วไหลของหน่วยความจำที่ไม่ได้ใช้งานใน Tomcat?

ดังนั้นฉันจึงสงสัยว่า: โปรแกรมที่เขียนใน Go จะแสดงการรั่วไหลของหน่วยความจำ (ที่ละเอียดอ่อนหรือไม่) แบบเดียวกับที่บางโปรแกรมที่เขียนด้วย Java จัดแสดงหรือไม่?


29
"โปรแกรม Java จำนวนมากมีการรั่วไหลของหน่วยความจำ (ละเอียดหรือไม่)" คุณมีหลักฐานเกี่ยวกับ "ข้อเท็จจริง" นี้หรือไม่หรือเป็นเพียงประเด็นพูดคุย
Peter Lawrey

17
@Webinator: ฉันคิดว่าคุณต้องยกตัวอย่างหนึ่งใน "การรั่วไหลของหน่วยความจำเล็กน้อย" ที่ "โปรแกรม Java" มีอยู่มากมาย เว้นแต่คุณจะอ้างว่ามีจุดบกพร่องในตัวรวบรวมขยะวิธีเดียวที่จะทำให้หน่วยความจำรั่วไหลใน Java บริสุทธิ์คือการยึดการอ้างอิงที่คุณไม่ได้ใช้อีกต่อไปเช่นการใส่วัตถุในคอลเล็กชันและห้ามลบออกจากคอลเล็กชันนั้น หากนี่คือการรั่วไหลที่คุณอ้างถึงไม่มีภาษาใดในโลกที่จะปกป้องพวกเขาได้รวมถึง Go
JeremyP

14
นี่คือการรั่วไหลของหน่วยความจำที่ฉันกำลังพูดถึง (+200 upvotes, คำตอบพร้อม +150 upvotes, อธิบายการรั่วไหลของหน่วยความจำ Java จำนวนมาก): stackoverflow.com/questions/6470651/…
SyntaxT3rr0r

6
แน่นอนว่าโปรแกรม JAVA มีหน่วยความจำรั่วเพียงแค่ลืมตั้งค่าการอ้างอิงบางส่วนเป็นค่าว่างเมื่อคุณต้องการใช้งานนานขึ้น เกิดขึ้นบ่อยครั้งในคอลเลกชันที่คงอยู่ขนาดใหญ่ (เช่นแคช) โดยมีรูปแบบการออกแบบผู้สังเกตการณ์หรือตัวแปรโลคัล นี่ไม่ใช่ทฤษฎีฉันแก้ไขหน่วยความจำที่รั่วไหลหลายครั้งในการผลิต และนี่ไม่ใช่การต่อต้าน Java ฉันเป็นนักพัฒนา JAVA แบบเต็มเวลามานานกว่า 5 ปีทำงานในโครงการต่างๆมากมาย การจำไม่ได้ว่าคุณอาจมีหน่วยความจำรั่วใน JAVA (หรือภาษาอื่น ๆ ที่มีอยู่) ไม่ใช่ลัทธิคลั่งไคล้ขาดความเข้าใจมากขึ้นว่าสิ่งต่างๆทำงานอย่างไร
Nicolas Bousquet

6
คำถามนี้สามารถทำได้โดยไม่ต้องดราม่าและความคิดเห็นเกี่ยวกับ "แฟนบอย" "เขย่าความเชื่อของใครบางคน" และสิ่งที่ชอบ Esp. เนื่องจากการอภิปรายทั้งหมดลงไปที่ "นิยามของฉันmemory leakดีกว่าของคุณ"
LAFK กล่าวว่า Reinstate Monica

คำตอบ:


44

คุณกำลังสับสนกับการรั่วไหลของหน่วยความจำประเภทต่างๆที่นี่

การรั่วไหลของหน่วยความจำที่ใช้การจัดการหน่วยความจำอย่างชัดเจนและร้ายแรงนั้นหายไปใน Java (หรือภาษาที่ใช้ GC อื่น ๆ ) การรั่วไหลเหล่านี้เกิดจากการสูญเสียการเข้าถึงหน่วยความจำโดยสิ้นเชิงโดยไม่ได้ทำเครื่องหมายว่าไม่ได้ใช้งาน

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


23
หน่วยความจำรั่วเกิดขึ้นเมื่อคุณลืมเพิ่มหน่วยความจำ ใน Java สิ่งนี้เกิดขึ้นเมื่อคุณลืมตั้งค่าการอ้างอิงเป็น null ใน C ++ จะเกิดขึ้นหากคุณลืมโทรฟรี ทั้งสองกรณีเป็นกรณีหน่วยความจำรั่วที่ถูกต้อง และปัญหาพื้นฐานก็เหมือนกันคุณโปรแกรมใช้หน่วยความจำมากขึ้นเรื่อย ๆ จนในที่สุดก็เกิดข้อผิดพลาด OutOfMemory
Nicolas Bousquet

1
แม้ว่าจะเป็นเรื่องจริงที่ไม่มีภาษาใดสามารถป้องกันไม่ให้โปรแกรมเมอร์สร้างข้อผิดพลาดทางตรรกะดังกล่าวได้ แต่ก็เป็นความจริงเช่นกันที่มีข้อผิดพลาดบางอย่างใน Java SDK (ดูตัวอย่างเช่นjava.util.logging.Levelซึ่งมีสแตติกส่วนตัวArrayListซึ่งอ็อบเจ็กต์ทั้งหมดที่สร้างขึ้น วางไว้บนโครงสร้างและไม่เคยลบออก) ซึ่งทำให้ยากที่จะหลีกเลี่ยงเมื่อเขียนโปรแกรม Java มากกว่าในภาษาอื่น ๆ ที่ไม่มีข้อบกพร่องดังกล่าว
Jules

7
ฉันคิดว่า OP กำลังถามเกี่ยวกับการรั่วไหลของหน่วยความจำของวัตถุที่ไม่สามารถเข้าถึงได้จริงๆเช่นในคำตอบที่ยอมรับของคำถามที่เชื่อมโยง หน่วยความจำรั่วที่เกิดจากการโหลดคลาสจากเธรด -1
qbt937

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

1
@Amrit ไม่ใช่ตัวเก็บขยะรวบรวมหน่วยความจำที่คุณไม่มีการอ้างอิงอีกต่อไป ไม่มีทางรู้ได้ว่าการลบบางสิ่งที่คุณยังมีอ้างอิงอยู่นั้นทำได้หรือไม่
Raphael Schmitz

19

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


1
ปัญหาอย่างหนึ่งของ mark and Sweep Collector ใน Java คือ memory fragementation แม้ว่าในทางเทคนิคจะไม่ใช่หน่วยความจำ แต่ก็สามารถสูญเสียหน่วยความจำที่มีอยู่ในแอปพลิเคชันได้
Peter Lawrey

9

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

"ภาษาไม่ทำให้หน่วยความจำรั่วโปรแกรมเมอร์ทำให้หน่วยความจำรั่ว"


8

การรวบรวมขยะหรือไม่คุณสามารถเขียนโปรแกรมที่มีการรั่วไหลของหน่วยความจำใน Java, Go หรือภาษาอื่น ๆ เป็นส่วนใหญ่

Garbage Collection ช่วยลดภาระบางส่วนของโปรแกรมเมอร์ แต่ไม่ได้ป้องกันการรั่วไหลทั้งหมด


4
ฉันรู้ว่าฉันรู้ว่า. ผมกำลังพูดถึงเฉพาะเกี่ยวกับบอบบางนะรั่วไหลของหน่วยความจำที่มีอยู่ใน Java ยากแม้ Java เป็นจุดเริ่มต้นของวางตลาดเป็นภาษาที่รั่วไหลของหน่วยความจำที่ไม่อยู่ต้องขอบคุณประชาคมโลก
SyntaxT3rr0r

4
ขออภัยที่ไม่ชัดเจน คุณบอกว่า "โปรแกรม Java จำนวนมากมีหน่วยความจำรั่ว (บอบบางหรือไม่)"
jzd

3

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

ดังนั้นปัญหาการรั่วไหลของหน่วยความจำจึงไม่ใช่ภาษาการเขียนโปรแกรมที่เฉพาะเจาะจงไม่มีเหตุผลที่ GO ควรจะดีกว่าหรือแย่กว่า Java


1
ฉันไม่เห็นด้วยอย่างสิ้นเชิง การรั่วไหลของหน่วยความจำเกิดจากการที่ Java ทำให้สามารถถ่ายภาพได้ด้วยตัวเองเพียงข้างเดียวและไม่จำเป็นต้องเกี่ยวข้องกับข้อผิดพลาดของไลบรารี โปรแกรมเมอร์จำนวนมากเขียนโปรแกรมที่ช้า แต่แน่นอนว่าหน่วยความจำรั่วไหลใน Java และนั่นเป็นความผิดของตัวเองไม่ใช่ความผิดของไลบรารี นอกจากนี้หาก Java GC ทำเวลาได้อย่างแม่นยำ / อาจเกิดการรั่วไหล Go จะทำการแลกเปลี่ยนเดียวกันหรือไม่?
SyntaxT3rr0r

1
และคำถามก็ไม่ใช่"ฉันต้องการใช้เวลาเท่าไหร่ในการค้นหาลูปดังกล่าว" คำถามคือ"ข้อกำหนดกำหนดให้ Go GC ใช้เวลากับลูปดังกล่าวนานเท่าใด"ซึ่ง IMHO เป็นคำถามที่น่าสนใจ
SyntaxT3rr0r

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