ตัวอย่าง Linux ที่รันได้น้อยที่สุดพร้อมการวิเคราะห์การแยกชิ้นส่วน
เนื่องจากนี่เป็นรายละเอียดการใช้งานที่ไม่ได้ระบุไว้โดยมาตรฐานลองมาดูกันว่าคอมไพเลอร์กำลังทำอะไรในการนำไปใช้งานเฉพาะ
ในคำตอบนี้ฉันจะลิงก์ไปยังคำตอบเฉพาะที่ทำการวิเคราะห์หรือให้การวิเคราะห์โดยตรงที่นี่และสรุปผลลัพธ์ทั้งหมดที่นี่
ทั้งหมดนั้นอยู่ในเวอร์ชัน Ubuntu / GCC ที่หลากหลายและผลลัพธ์น่าจะค่อนข้างคงที่ในทุกเวอร์ชัน แต่ถ้าเราพบรูปแบบที่แตกต่างกันให้ระบุรุ่นที่แม่นยำกว่านี้
ตัวแปรโลคัลภายในฟังก์ชัน
ไม่ว่าจะเป็นmain
หรือฟังก์ชั่นอื่น ๆ :
void f(void) {
int my_local_var;
}
ดังที่: ที่ <value optimization out> หมายถึงอะไรใน gdb?
-O0
: ซ้อนกัน
-O3
: ลงทะเบียนหากพวกเขาไม่รั่วไหลซ้อนเป็นอย่างอื่น
สำหรับแรงจูงใจว่าทำไมสแต็คจึงมีอยู่ดู: อะไรคือฟังก์ชั่นของคำแนะนำแบบพุช / ป๊อปที่ใช้กับรีจิสเตอร์ในชุดประกอบ x86?
ตัวแปรโกลบอลและstatic
ตัวแปรฟังก์ชัน
/* BSS */
int my_global_implicit;
int my_global_implicit_explicit_0 = 0;
/* DATA */
int my_global_implicit_explicit_1 = 1;
void f(void) {
/* BSS */
static int my_static_local_var_implicit;
static int my_static_local_var_explicit_0 = 0;
/* DATA */
static int my_static_local_var_explicit_1 = 1;
}
- หากเริ่มต้นไปที่
0
หรือไม่เริ่มต้น (และเริ่มต้นโดยปริยายไป0
) .bss
ส่วน: ดูเพิ่มเติม: ทำไมส่วน. BSS จำเป็น?
- มิฉะนั้น:
.data
ส่วน
char *
และ char c[]
ดังที่: ตัวแปรสแตติกเก็บอยู่ที่ไหนใน C และ C ++?
void f(void) {
/* RODATA / TEXT */
char *a = "abc";
/* Stack. */
char b[] = "abc";
char c[] = {'a', 'b', 'c', '\0'};
}
สิ่งที่ต้องทำจะเป็นตัวอักษรสตริงที่มีขนาดใหญ่มากนอกจากนี้ยังวางบนกอง? หรือ.data
? หรือการรวบรวมล้มเหลว?
อาร์กิวเมนต์ของฟังก์ชัน
void f(int i, int j);
ต้องผ่านระเบียบการโทรที่เกี่ยวข้องเช่น: https://en.wikipedia.org/wiki/X86_calling_conventionsสำหรับ X86 ซึ่งระบุการลงทะเบียนเฉพาะหรือตำแหน่งสแต็กสำหรับแต่ละตัวแปร
จากนั้นตามที่แสดงที่<value Optimization out> หมายถึงอะไรใน gdb? , -O0
แล้ว slurps ทุกอย่างลงในสแต็คในขณะที่-O3
พยายามที่จะใช้ลงทะเบียนมากที่สุดเท่าที่เป็นไปได้
หากฟังก์ชั่นได้รับการอินไลน์ฟังก์ชันเหล่านั้นจะได้รับการปฏิบัติเหมือนเป็นไอเดียทั่วไป
const
ฉันเชื่อว่ามันไม่ได้ทำให้แตกต่างเพราะคุณสามารถพิมพ์มันออกไปได้
ในทางกลับกันหากคอมไพเลอร์สามารถตรวจสอบได้ว่าข้อมูลบางอย่างไม่เคยถูกเขียนลงไปในทางทฤษฎีแล้วมันอาจวางไว้ในทฤษฎี.rodata
แม้ว่าจะไม่ใช่ const
การวิเคราะห์สิ่งที่ต้องทำ
ตัวชี้
พวกเขาเป็นตัวแปร (ที่มีที่อยู่ซึ่งเป็นตัวเลข) เช่นเดียวกับส่วนที่เหลือทั้งหมด :-)
malloc
คำถามไม่สมเหตุสมผลmalloc
นักเนื่องจากmalloc
เป็นฟังก์ชันและใน:
int *i = malloc(sizeof(int));
*i
เป็นตัวแปรที่มีที่อยู่ดังนั้นจึงตรงกับตัวพิมพ์ใหญ่ด้านบน
สำหรับวิธีที่ malloc ทำงานภายในเมื่อคุณเรียกใช้เคอร์เนล Linux จะทำเครื่องหมายที่อยู่บางอย่างว่าสามารถเขียนได้บนโครงสร้างข้อมูลภายในและเมื่อพวกเขาถูกสัมผัสโดยโปรแกรมในตอนแรกข้อผิดพลาดจะเกิดขึ้นและเคอร์เนลจะเปิดใช้งานตารางหน้า เกิดขึ้นได้โดยไม่ต้องมี segfaul: เพจ x86 ทำงานอย่างไร
อย่างไรก็ตามโปรดทราบว่านี่เป็นสิ่งที่exec
syscall ทำภายใต้ฮู้ดเมื่อคุณพยายามเรียกใช้ปฏิบัติการ: ทำเครื่องหมายหน้าเว็บที่ต้องการโหลดและเขียนโปรแกรมที่นั่นดูที่: เคอร์เนลรับไบนารีไฟล์ที่ปฏิบัติการได้ ลินุกซ์? ยกเว้นว่าexec
มีข้อ จำกัด เพิ่มเติมบางประการเกี่ยวกับตำแหน่งที่โหลดไป (เช่นรหัสไม่สามารถย้ายตำแหน่งได้ )
syscall ที่แน่นอนที่ใช้สำหรับmalloc
เป็นmmap
ในปัจจุบัน 2020 การใช้งานและในอดีตที่ผ่านมาbrk
ได้ถูกใช้: ไม่ malloc () ใช้ brk () หรือ mmap ()?
ห้องสมุดแบบไดนามิก
โดยพื้นฐานรับmmap
หน่วยความจำ ed: /unix/226524/what-system-call-is-used-to-load-l ไลบรารี-in-linux/462710 # 462710
ตัวแปร envinroment และmain
'sargv
ด้านบนสแต็กเริ่มต้น: /unix/75939/where-is-the-environment-string-actual-storedสิ่งที่ต้องทำทำไมไม่อยู่ใน. data?