หน่วยความจำถูกจัดสรรให้กับตัวแปรคงที่ส่วนกลางที่กำหนดใน cpp เพิ่มขึ้นหลังจากอินสแตนซ์ของคลาสถูกลบใน C ++ หรือไม่

ฉันมีคลาสที่มีวิธีการกำหนดไว้ในไฟล์ example.cpp และคลาสที่กำหนดใน example.h มีตัวชี้ส่วนกลางแบบคงที่ที่กำหนดไว้ในไฟล์ example.cpp (ฉันต้องการตัวชี้นี้ที่กำหนดให้เป็นตัวชี้ส่วนกลางแบบคงที่ใน .cpp เนื่องจากถูกเรียกในรูทีนบริการขัดจังหวะแบบคงที่ที่ทำงานบนระบบ Bare-Metal) ฉันสงสัยว่า เมื่อใดที่อินสแตนซ์ของคลาสนี้ถูกลบ หน่วยความจำที่จัดสรรให้กับตัวชี้ส่วนกลางแบบคงที่นี้ ซึ่งกำหนดไว้ภายนอกคลาส (ภายในไฟล์ cpp เป็นตัวแปรส่วนกลางแบบคงที่) ทำให้ว่างขึ้นเช่นกัน? ฉันกังวลเกี่ยวกับปัญหาหน่วยความจำรั่ว (โปรดอย่าแนะนำอะไรด้วยตัวชี้อัจฉริยะ ขอบคุณ)

// example.cpp
#include <example.h>
static example* ptr;
example::example(){ prt = this; }
example::~example(){}

// example.h
class example
{
public:
example();
virtual ~example();
int a;
};

//main.c
void main(void)
{
  while(1){
           example eg1;
           delete &eg1;
           }
  //Has all the memory allocated to eg1 been freed up including the global static variable(a pointer)?
}

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

นี่เป็นครั้งแรกที่ฉันถามคำถามที่นี่ ขออภัยล่วงหน้าหากมีสิ่งใดไม่ชัดเจน


person TyL    schedule 12.03.2015    source แหล่งที่มา
comment
ใครบ้างที่ไม่เพียงแต่ใช้รูปแบบการออกแบบซิงเกิลตัน?   -  person Lawrence Aiello    schedule 12.03.2015
comment
new และ Delete ต้องใช้คู่กัน ตอนนี้คุณเห็นแล้วว่าโค้ดของคุณมีปัญหาอะไร?   -  person billz    schedule 12.03.2015
comment
ฉันแน่ใจว่าคุณทราบดีว่าคำสั่ง delete &eg1 ของคุณมีทั้งผิดอย่างร้ายแรงและไม่จำเป็นเลย...   -  person Lightness Races in Orbit    schedule 13.03.2015


คำตอบ (4)


ก่อนอื่น หากคุณรันโค้ดที่คุณโพสต์ คุณจะได้รับสิ่งต่อไปนี้:

malloc: *** error for object 0x7fff560a8830: pointer being freed was not allocated

เนื่องจากคุณลบ &eg1 โดยไม่ได้จัดสรรหน่วยความจำบนฮีปก่อนโดยใช้ new

ประการที่สอง destructor/delete จะล้างเฉพาะหน่วยความจำที่เกี่ยวข้องกับวัตถุ example ไม่มีข้อผูกมัดในการล้างข้อมูล static example* ptr

เมื่อพิจารณาอีกวิธีหนึ่ง destructors และ delete มีไว้เพื่อล้างข้อมูลที่จัดสรรแบบไดนามิก เช่น ข้อมูลที่อยู่บนฮีป ไม่ใช่แค่บนสแต็กของการเรียกใช้ฟังก์ชันปัจจุบัน ในทางตรงกันข้าม static example* ptr เป็นโกลบอลซึ่งอยู่ในเซ็กเมนต์ข้อมูลโกลบอล แยกจากฮีปและสแต็ก

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

แก้ไข ------------------

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

มีเรื่องให้รวบรวมมากมายที่นี่! static อาจทำให้สับสนในช่วงแรก แต่ความรู้ที่ดีเกี่ยวกับเรื่องนี้จะช่วยได้มาก

person CLL    schedule 12.03.2015

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

นอกจากนี้ การทำลายตัวชี้ (ที่ไม่ฉลาด) ไม่เคย จะทำลายสิ่งที่ตัวชี้ชี้ไป คุณต้องเรียก delete บนตัวชี้อย่างชัดเจนหากคุณต้องการเพิ่มทรัพยากรที่ตัวชี้ไป (หรือใช้ตัวชี้อัจฉริยะทำจะดีกว่า)

person rici    schedule 12.03.2015
comment
ขอบคุณที่ตอบ แต่ฉันอาจทำให้คุณเข้าใจผิดที่นี่ ฉันไม่สนใจหน่วยความจำของตัวชี้ที่ชี้ไป แต่จริงๆ แล้วหน่วยความจำที่จัดสรรเพื่อจัดเก็บตัวชี้นั้นเอง ฉันแค่เปลี่ยนรหัสเล็กน้อยเพื่อให้ชัดเจนยิ่งขึ้น - person TyL; 13.03.2015
comment
@TyL: นั่นเป็นหัวข้อของย่อหน้าแรกของฉัน อายุการใช้งานของสิ่งใดก็ตามแบบคงที่คืออายุการใช้งานของโปรแกรมตามคำจำกัดความ - person rici; 13.03.2015
comment
คุณกำลังบอกว่าตัวแปรส่วนกลางแบบคงที่นั้นถูกแชร์กับอินสแตนซ์ทั้งหมดของคลาสนี้ด้วยหรือไม่ (ฉันคิดว่าจะสามารถแชร์ได้ก็ต่อเมื่อมีการกำหนดภายในชั้นเรียนให้เป็นสมาชิกมากกว่าที่จะอยู่นอกชั้นเรียน) มิฉะนั้นตัวแปรคงที่จะไม่ทราบว่าฉันจะสร้างคลาสนี้กี่อินสแตนซ์ คุณคิดว่าการวนรอบ while(1) ใน main.c ของฉันจะทำให้หน่วยความจำรั่วหรือไม่ - person TyL; 13.03.2015
comment
@tyl: มีตัวแปรส่วนกลางแบบคงที่เพียงตัวเดียวเท่านั้น ทำไมคุณถึงคิดว่ามันจะเกี่ยวข้องกับอินสแตนซ์ของชั้นเรียน? มันเป็นเพียงคำจำกัดความสากลที่ไม่มีการเชื่อมโยงภายนอก - person rici; 13.03.2015
comment
ตกลง. ฉันเห็นแล้ว. ขอบคุณมาก!!!!!!! ฉันเอาแต่คิดว่ามันจะถูกสร้างขึ้นเมื่อมีการสร้างตัวอย่างขึ้นมา.... - person TyL; 13.03.2015
comment
ไม่ได้ระบุลำดับการทำลายสถิติ มันเป็นการกลับกันของการก่อสร้าง และมันจะเกิดขึ้นหลังจาก main กลับมา - person Alan Stokes; 13.03.2015
comment
@AlanStokes: ใช่ แต่ไม่ได้ระบุลำดับการสร้างสถิติในหน่วยการแปลที่แตกต่างกัน ดังนั้นจึงไม่มีคำสั่งในการทำลายล้าง บางทีถ้าไม่ระบุให้ครบถ้วนจะแม่นยำกว่านี้ - person rici; 13.03.2015

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

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

นอกจากนี้ คุณไม่จำเป็นต้องเรียก Delete ใน main() เนื่องจาก eg1 เป็นตัวแปรภายในเครื่อง เมื่อ main กลับมา destructor ของ eg1 จะถูกเรียกโดยอัตโนมัติ

person Vivek    schedule 12.03.2015
comment
ขอบคุณ. มันมีประโยชน์จริงๆ คุณกำลังบอกว่าตัวแปรส่วนกลางแบบคงที่นั้นถูกแชร์กับอินสแตนซ์ทั้งหมดของคลาสนี้ด้วยหรือไม่ (ฉันคิดว่าจะสามารถแชร์ได้เฉพาะเมื่อมีการกำหนดในชั้นเรียนมากกว่านอกชั้นเรียน) - person TyL; 13.03.2015
comment
ตัวแปรส่วนกลางแบบคงที่สามารถเข้าถึงได้โดยทุกอินสแตนซ์ของคลาส และจะถูกเขียนทับทุกครั้งที่สร้างออบเจ็กต์ตัวอย่างใหม่ แม้ว่าตัวแปรนั้นจะถูกสร้างเป็นตัวแปรสมาชิกคลาสแบบสแตติก มันก็จะถูกเขียนทับในลักษณะเดียวกัน ดังนั้น แทนที่จะกำหนดตัวแปรโกลบอลในตัวสร้างคลาส การกำหนดตัวแปรให้กับ &eg1 ใน main() จะช่วยให้แน่ใจว่าตัวแปรจะไม่ถูกเขียนทับ - person Vivek; 13.03.2015

ไม่ ออบเจ็กต์ตัวชี้ static ไม่มีลิงก์ภายในไปยังคลาส example และแน่นอนว่าไม่มีลิงก์ภายในไปยังออบเจ็กต์ eg1 หากระบบทำลาย ptr เพียงเพราะ eg1 อยู่นอกขอบเขต ภาษาจะมากใช้งานไม่ได้

person Lightness Races in Orbit    schedule 12.03.2015