ความเป็นไปได้สำหรับการจัดสรรหน่วยความจำสำหรับการออกแบบเฟิร์มแวร์แบบแยกส่วนใน C


16

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

ตอนนี้ฉันสงสัยว่าวิธีที่ดีที่สุดของหน่วยความจำการจัดสรรสำหรับโครงสร้างที่อธิบายถึงโมดูลอาจเป็น ถ้าเป็นไปได้ฉันต้องการสิ่งต่อไปนี้:

  • โครงสร้างทึบแสงดังนั้นโครงสร้างอาจเปลี่ยนแปลงได้โดยการใช้ฟังก์ชั่นอินเตอร์เฟสที่มีให้เท่านั้น
  • หลายกรณี
  • หน่วยความจำที่จัดสรรโดย linker

ฉันเห็นความเป็นไปได้ดังต่อไปนี้ซึ่งขัดแย้งกับหนึ่งในเป้าหมายของฉัน:

ประกาศทั่วโลก

หลายอินสแตนซ์ทั้งหมดถูกลิงค์โดย linker แต่ struct ไม่ทึบแสง

(#includes)
module_struct module;

void main(){
   module_init(&module);
}

malloc

opaque โครงสร้างหลายอินสแตนซ์แต่ allcotion on heap

ใน module.h:

typedef module_struct Module;

ในฟังก์ชั่น module.c init, malloc และตัวชี้กลับไปยังหน่วยความจำที่จัดสรรไว้

module_mem = malloc(sizeof(module_struct ));
/* initialize values here */
return module_mem;

ใน main.c

(#includes)
Module *module;

void main(){
    module = module_init();
}

ประกาศในโมดูล

opaque struct ซึ่งจัดสรรโดย linker จำนวนอินสแตนซ์ที่กำหนดไว้ล่วงหน้าเท่านั้น

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

(#includes)

void main(){
    module_init(_no_param_or_index_if_multiple_instances_possible_);
}

มีตัวเลือกในการรวมสิ่งเหล่านี้สำหรับโครงสร้างทึบแสง, linker แทนการจัดสรรฮีปและอินสแตนซ์จำนวนมาก / หลาย ๆ ครั้งหรือไม่?

วิธีการแก้

ตามที่เสนอในคำตอบบางข้อด้านล่างฉันคิดว่าวิธีที่ดีที่สุดคือ:

  1. จองพื้นที่สำหรับโมดูล MODULE_MAX_INSTANCE_COUNT ในไฟล์ซอร์สโมดูล
  2. ห้ามกำหนด MODULE_MAX_INSTANCE_COUNT ในโมดูลของตนเอง
  3. เพิ่ม #ifndef MODULE_MAX_INSTANCE_COUNT #error ไปยังไฟล์ส่วนหัวโมดูลเพื่อให้แน่ใจว่าผู้ใช้โมดูลทราบถึงข้อ จำกัด นี้และกำหนดจำนวนอินสแตนซ์สูงสุดที่ต้องการสำหรับแอปพลิเคชัน
  4. ในการเริ่มต้นของอินสแตนซ์กลับทั้งที่อยู่หน่วยความจำ (* เป็นโมฆะ) ของโครงสร้าง desricptive หรือดัชนีโมดูล (สิ่งที่คุณต้องการมากขึ้น)

12
นักออกแบบ FW ที่ฝังตัวส่วนใหญ่กำลังหลีกเลี่ยงการจัดสรรแบบไดนามิกเพื่อให้การใช้งานหน่วยความจำเสื่อมถอยและเรียบง่าย โดยเฉพาะอย่างยิ่งหากเป็นโลหะเปลือยและไม่มี OS พื้นฐานในการจัดการหน่วยความจำ
ยูจีน Sh.

นั่นคือเหตุผลที่ฉันต้องการให้ตัวเชื่อมโยงทำการจัดสรร
แอลเฮ็นริช

4
ฉันค่อนข้างไม่แน่ใจว่าฉันเข้าใจ ... คุณจะจัดสรรหน่วยความจำโดย linker ได้อย่างไรถ้าคุณมีอินสแตนซ์จำนวนไดนามิก? ที่ดูเหมือนว่าค่อนข้างฉากสำหรับฉัน
jcaron

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

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

คำตอบ:


4

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

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

จากนั้นไฟล์ต้นฉบับที่มีการประกาศ struct จริงและฟังก์ชั่นที่เกี่ยวข้องทั้งหมดจะประกาศอาร์เรย์ของอินสแตนซ์ที่มีการเชื่อมโยงภายใน มันมีทั้งอาเรย์ที่มีการเชื่อมโยงภายนอกของตัวชี้ไปยังอินสแตนซ์หรืออื่น ๆ ฟังก์ชั่นสำหรับการเข้าถึงตัวชี้ต่างๆโดยดัชนี รูปแบบฟังก์ชั่นเป็นมอดูลาร์มากขึ้นอีกเล็กน้อย:

module.c

#include <module.h>

// 4 instances by default; can be overridden at compile time
#ifndef NUM_MODULE_INSTANCES
#define NUM_MODULE_INSTANCES 4
#endif

struct module {
    int demo;
};

// has internal linkage, so is not directly visible from other files:
static struct module instances[NUM_MODULE_INSTANCES];

// module functions

struct module *module_init(unsigned index) {
    instances[index].demo = 42;
    return &instances[index];
}

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

module.h

#ifndef MODULE_H
#define MODULE_H

struct module;

struct module *module_init(unsigned index);

// other functions ...

#endif

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


*ถ้าคุณไม่คัดลอกคำจำกัดความของหลักสูตร ประเด็นก็คือmodule.hไม่ได้ทำเช่นนั้น


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

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

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

@ L.Heinrichs ใช่แล้วเนื่องจากระบบฝังตัวนั้นมีลักษณะที่กำหนดไว้ได้ ไม่มีสิ่งเช่น "จำนวนวัตถุที่ไม่มีที่สิ้นสุด" หรือ "จำนวนวัตถุที่ไม่รู้จัก" วัตถุก็มักจะเป็นแบบซิงเกิลตันเช่นกัน (ไดรเวอร์ฮาร์ดแวร์) ดังนั้นจึงไม่จำเป็นต้องมีพูลหน่วยความจำเนื่องจากจะมีเพียงหนึ่งอินสแตนซ์เดียวของวัตถุ
Lundin

ฉันเห็นด้วยกับกรณีส่วนใหญ่ คำถามก็มีความสนใจทางทฤษฎีเช่นกัน แต่ฉันสามารถใช้เซ็นเซอร์อุณหภูมิ 1 สายหลายร้อยสายได้หากมี IOs เพียงพอ (เช่นหนึ่งตัวอย่างที่ฉันสามารถหามาได้ในตอนนี้)
L. Heinrichs

22

ฉันตั้งโปรแกรมไมโครคอนโทรลเลอร์ขนาดเล็กใน C ++ ซึ่งบรรลุสิ่งที่คุณต้องการ

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

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

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

การพูดคุยของฉันเกี่ยวกับวิธีการเข้ารหัสนี้ใน C ++: วัตถุ ไม่เป็นไรขอบคุณ!

จำนวนมากฝัง / โปรแกรมเมอร์ไมโครคอนโทรลเลอร์ดูเหมือนจะไม่ชอบ c ++ เพราะพวกเขาคิดว่ามันจะบังคับให้พวกเขาที่จะใช้ทั้งหมดของ C ++ นั่นไม่ใช่สิ่งจำเป็นอย่างยิ่งและจะเป็นความคิดที่แย่มาก (คุณอาจไม่ได้ใช้ C ทั้งหมดเช่นกันคิดว่า heap, floating point, setjmp / longjmp, printf, ... )


ในความคิดเห็น Adam Haun กล่าวถึง RAII และการเริ่มต้น IMO RAII มีส่วนเกี่ยวข้องกับ deconstruction มากขึ้น แต่ประเด็นของเขานั้นถูกต้อง: วัตถุทั่วโลกจะถูกสร้างขึ้นก่อนที่คุณจะเริ่มหลักดังนั้นพวกเขาอาจทำงานบนสมมติฐานที่ไม่ถูกต้อง (เช่นความเร็วสัญญาณนาฬิกาหลักที่จะเปลี่ยนในภายหลัง) นั่นเป็นอีกเหตุผลหนึ่งที่ไม่ควรใช้ออบเจ็กต์เริ่มต้นด้วยรหัสสากล (ฉันใช้สคริปต์ตัวเชื่อมโยงที่จะล้มเหลวเมื่อฉันมีออบเจ็กต์ที่เริ่มต้นด้วยรหัสสากล) IMO ควรสร้าง 'วัตถุ' อย่างชัดเจนและส่งผ่าน ซึ่งรวมถึงวัตถุ 'กำลังรอ' สิ่งอำนวยความสะดวก 'ที่มีฟังก์ชั่นการรอ () ในการตั้งค่าของฉันนี่คือ 'วัตถุ' ที่ตั้งค่าความเร็วสัญญาณนาฬิกาของชิป

การพูดเกี่ยวกับ RAII: นั่นเป็นอีกคุณสมบัติ C ++ ที่มีประโยชน์อย่างมากในระบบฝังตัวเล็ก ๆ แม้ว่าจะไม่ใช่เหตุผล (การจัดสรรคืนหน่วยความจำ) ซึ่งส่วนใหญ่จะใช้สำหรับระบบที่ใหญ่กว่า (ระบบฝังตัวเล็ก ๆ ส่วนใหญ่ไม่ใช้การจัดสรรคืนหน่วยความจำแบบไดนามิก) คิดถึงการล็อคทรัพยากร: คุณสามารถทำให้ทรัพยากรที่ถูกล็อคเป็นวัตถุห่อหุ้มและ จำกัด การเข้าถึงทรัพยากรให้เป็นไปได้โดยผ่านเครื่องห่อหุ้มล็อคเท่านั้น เมื่อ wrapper อยู่นอกขอบเขตทรัพยากรจะถูกปลดล็อค วิธีนี้ช่วยป้องกันการเข้าถึงโดยไม่ล็อคและทำให้มีโอกาสน้อยมากที่จะลืมการปลดล็อค ด้วยเวทย์มนตร์บางอย่าง (เทมเพลต) อาจเป็นศูนย์ได้


คำถามเดิมไม่ได้พูดถึง C ดังนั้น C ++ ของฉันเป็นคำตอบที่เป็นศูนย์กลาง ถ้าเป็นจริงต้องเป็น C ....

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

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


@Lundins แสดงความคิดเห็นเกี่ยวกับโปรแกรมเมอร์ (ฝัง) ที่ไม่ดี:

  • ประเภทของโปรแกรมเมอร์ที่คุณอธิบายอาจจะยุ่งเหยิงในภาษาใด ๆ มาโคร (แสดงใน C และ C ++) เป็นวิธีหนึ่งที่ชัดเจน

  • การขับรถสามารถช่วยได้บ้าง สำหรับนักเรียนของฉันฉันได้รับคำสั่งสคริปต์ที่สร้างขึ้นซึ่งระบุว่าไม่มีข้อยกเว้น no-rtti และให้ข้อผิดพลาด linker เมื่อมีการใช้ฮีปหรือฮีปเริ่มต้นโค้ดที่เริ่มต้น และมันจะระบุ warning = error และเปิดใช้งานคำเตือนเกือบทั้งหมด

  • ฉันสนับสนุนให้ใช้เทมเพลต แต่ด้วย constexpr และแนวคิด metaprogramming นั้นมีความจำเป็นน้อยลง

  • "โปรแกรมเมอร์ Arduino สับสน" ฉันอยากจะแทนที่รูปแบบการเขียนโปรแกรม Arduino (เดินสาย, การจำลองรหัสในห้องสมุด) ด้วยวิธีการ C ++ ที่ทันสมัยซึ่งสามารถใช้งานได้ง่ายขึ้นปลอดภัยขึ้นและสร้างโค้ดที่เร็วขึ้นและเล็กลง ถ้าเพียง แต่ฉันมีเวลาและพลังงาน ....


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

เหตุใดคุณใช้ (เฉพาะ) C บางทีนี่อาจทำให้คุณมีโอกาสโน้มน้าวใจพวกเขาให้พิจารณา C ++ เป็นอย่างน้อย ... สิ่งที่คุณต้องการคือสิ่งจำเป็น (ส่วนเล็ก ๆ ของ) C ++ ที่รู้ใน C
Wouter van Ooijen

สิ่งที่ฉันทำในของฉัน (แรก 'จริง' โครงการงานอดิเรกที่ฝังตัว) คือการเริ่มต้นเริ่มต้นง่ายๆในการสร้างและใช้วิธีการแยกต่างหากสำหรับชั้นเรียนที่เกี่ยวข้อง ประโยชน์อีกอย่างคือฉันสามารถผ่านตัวชี้ต้นขั้วสำหรับการทดสอบหน่วย
Michel Keijzers

2
@Michel สำหรับโปรเจ็กต์งานอดิเรกคุณมีอิสระในการเลือกภาษาได้ไหม? รับ C ++!
Wouter van Ooijen

4
และในขณะที่เป็นไปได้อย่างสมบูรณ์แบบในการเขียนโปรแกรม C ++ ที่ดีสำหรับการฝังตัวปัญหาคือบางส่วน> 50% ของโปรแกรมเมอร์ระบบฝังตัวทั้งหมดมี quacks, โปรแกรมเมอร์ PC ที่สับสน, มือสมัครเล่น Arduino ฯลฯ ฯลฯ คนประเภทนี้ไม่สามารถใช้ ทำความสะอาดชุดย่อยของ C ++ แม้ว่าคุณจะอธิบายให้ใบหน้าของพวกเขาเห็น ให้ C ++ แก่พวกเขาและก่อนที่คุณจะรู้พวกเขาจะใช้ STL ทั้งหมด, เทมเพลต metaprogramming, การจัดการข้อยกเว้น, การสืบทอดหลายรายการและอื่น ๆ และผลลัพธ์ก็คือถังขยะที่สมบูรณ์แบบแน่นอน นี่เป็นเรื่องเศร้าที่โครงการฝังตัว C ++ 8 โครงการจากทั้งหมด 10 โครงการสิ้นสุดลง
Lundin

7

ฉันเชื่อว่า FreeRTOS (อาจเป็นระบบปฏิบัติการอีกระบบ) ทำสิ่งที่คุณต้องการโดยการกำหนดโครงสร้างของรุ่นต่าง ๆ 2 แบบ
หนึ่ง 'ของจริง' ที่ใช้ภายในโดยฟังก์ชั่นระบบปฏิบัติการและหนึ่งของ 'ปลอม' ซึ่งมีขนาดเดียวกับของจริง 'แต่ไม่มีสมาชิกที่มีประโยชน์ภายใน (เพียงพวงint dummy1และคล้ายกัน)
มีเพียงโครงสร้าง 'ปลอม' เท่านั้นที่เปิดเผยนอกรหัส OS และใช้เพื่อจัดสรรหน่วยความจำให้กับอินสแตนซ์แบบคงที่ของโครงสร้าง
ภายในเมื่อฟังก์ชั่นในระบบปฏิบัติการถูกเรียกพวกเขาจะถูกส่งผ่านที่อยู่ของโครงสร้าง 'ปลอม' ภายนอกเป็นจุดจับและนี่คือ typecast เป็นตัวชี้ไปยังโครงสร้าง 'ของจริง' เพื่อให้ฟังก์ชั่นระบบปฏิบัติการสามารถทำสิ่งที่พวกเขาต้องการ ทำ.


ความคิดที่ดีฉันคิดว่าฉันสามารถใช้ --- #define BUILD_BUG_ON (เงื่อนไข) ((เป็นโมฆะ) ขนาดของ (char [1 - 2 * !! (เงื่อนไข)])) --- BUILD_BUG_ON (ขนาดของ (real_struct)! = sizeof ( fake_struct)) ----
L. Heinrichs

2

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

ในความคิดของฉันนี้ไม่มีจุดหมาย คุณสามารถใส่ความคิดเห็นได้ แต่ไม่มีจุดใดที่พยายามซ่อนความคิดเห็นเพิ่มเติม

C จะไม่ให้ความโดดเดี่ยวสูงเช่นนี้แม้ว่าจะไม่มีการประกาศสำหรับ struct มันจะง่ายที่จะเขียนทับมันด้วยเช่นตั้งใจเข้าใจผิด memcpy () หรือล้นบัฟเฟอร์

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


2

คำถาม SW บริสุทธิ์จะถามดีกว่าที่/programming/

แนวคิดที่เปิดเผยโครงสร้างของประเภทที่ไม่สมบูรณ์แก่ผู้โทรเช่นที่คุณอธิบายมักเรียกว่า "opaque type" หรือ "opaque pointers" - struct ที่ไม่ระบุตัวตนหมายถึงสิ่งอื่นทั้งหมด

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

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

ดูการจัดสรรแบบคงที่ของชนิดข้อมูลทึบแสงที่ SO


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