ตัวแปรของฉันถูกเก็บไว้ในหน่วยความจำที่ไหน


156

โดยพิจารณาว่าหน่วยความจำแบ่งออกเป็นสี่ส่วน: data, heap, stack และ code โดยที่ตัวแปรโกลบอล, ตัวแปรสแตติก, ชนิดข้อมูลคงที่, ตัวแปรโลคัล (กำหนดและประกาศในฟังก์ชัน), ตัวแปร (ในฟังก์ชั่นหลัก), พอยน์เตอร์ และพื้นที่ที่จัดสรรแบบไดนามิก (โดยใช้ malloc และ calloc) จะถูกเก็บไว้ในหน่วยความจำหรือไม่?

ฉันคิดว่าพวกเขาจะได้รับการจัดสรรดังนี้:

  • ตัวแปรโกลบอล -------> ข้อมูล
  • ตัวแปรคงที่ -------> ข้อมูล
  • ประเภทข้อมูลคงที่ -----> รหัส
  • ตัวแปรท้องถิ่น (ประกาศและกำหนดไว้ในฟังก์ชั่น) --------> สแต็ค
  • ตัวแปรที่ประกาศและกำหนดในฟังก์ชั่นหลัก -----> heap
  • พอยน์เตอร์ (ตัวอย่างเช่นchar *arr, int *arr) -------> heap
  • พื้นที่ที่จัดสรรแบบไดนามิก (โดยใช้ malloc และ calloc) --------> stack

ฉันหมายถึงตัวแปรเหล่านี้จากมุมมอง C เท่านั้น

โปรดแก้ไขให้ฉันถ้าฉันผิดเพราะฉันยังใหม่กับ C.


4
ประเภทจะไม่ถูกเก็บไว้ในหน่วยความจำ

5
mainเป็นเพียงฟังก์ชั่นอื่น ตัวแปรจะอยู่ในสแต็กเว้นแต่จะmallocเหมือนกับที่อื่น
simonc

4
พอยน์เตอร์ (โดยปกติ) เก็บไว้ในสแต็ก หน่วยความจำที่พวกเขาชี้ไปที่ (มักจะจัดสรรผ่าน malloc / calloc) คือ (โดยปกติ) บนฮีป
jpm

3
พื้นที่ที่จัดสรรแบบไดนามิก (ใช้ malloc, calloc) --------> heap
One Man Crew

3
ตัวแปรที่ประกาศและกำหนดในฟังก์ชั่นหลัก -----> stack
One Man Crew

คำตอบ:


217

คุณมีสิทธิ์เหล่านี้บ้าง แต่ใครก็ตามที่เขียนคำถามที่หลอกคุณอย่างน้อยหนึ่งคำถาม:

  • ตัวแปรโกลบอล -------> ข้อมูล (ถูกต้อง)
  • ตัวแปรคงที่ -------> data (ถูกต้อง)
  • ประเภทข้อมูลคงที่ -----> รหัสและ / หรือข้อมูล พิจารณาตัวอักษรสตริงสำหรับสถานการณ์เมื่อค่าคงที่จะถูกเก็บไว้ในส่วนของข้อมูลและการอ้างอิงนั้นจะถูกฝังอยู่ในรหัส
  • ตัวแปรท้องถิ่น (ประกาศและกำหนดในฟังก์ชั่น) --------> สแต็ก (ถูกต้อง)
  • ตัวแปรที่ประกาศและกำหนดไว้ในmainฟังก์ชั่น -----> heapยังสแต็ก (ครูพยายามหลอกคุณ)
  • ตัวชี้ (เช่น: char *arr, int *arr) -------> กองข้อมูลหรือกองขึ้นอยู่กับบริบท C ช่วยให้คุณประกาศโกลบอลหรือstaticพอยน์เตอร์ซึ่งในกรณีนี้พอยน์เตอร์จะจบลงในส่วนของข้อมูล
  • จัดสรรพื้นที่แบบไดนามิก (ใช้malloc, calloc, realloc) --------> สแต็คกอง

เป็นมูลค่าการกล่าวขวัญว่า "กอง" อย่างเป็นทางการเรียกว่า "ชั้นจัดเก็บอัตโนมัติ"


6
นอกจากนี้มูลค่าการกล่าวขวัญว่ากองอย่างเป็นทางการไม่ได้เรียกอะไรเลย หน่วยความจำที่จัดสรรมาจากที่ไหนสักแห่งไม่มีชื่อในมาตรฐานสำหรับ "ที่ไหนสักแห่ง"
Steve Jessop

6
ในบางระบบ (เช่น Linux และ * BSD) ก็มีระบบallocaที่ทำงานคล้ายกันmallocแต่มีการจัดสรรสแต็ก
Andreas Grapentin

ตัวแปร const ที่ประกาศในเมธอดไปที่ใด
Mahori

@Ravi สถานที่เดียวกันกับค่าคงที่ที่เหลือ (จุด # 3 ด้านบน)
dasblinkenlight

ฉันใช้ GCC 4.8.1 และดูเหมือนว่าจะไม่เก็บตัวแปร const ท้องถิ่นเป็นหลักในส่วนข้อมูล ด้านล่างนี้คือรหัสและแมปหน่วยความจำสำหรับ 3 โปรแกรมดังกล่าว: รหัส 1: int main (void) {// char a [10] = "HELLO"; // 1 // const char a [10] = "HELLO"; // 2 คืนค่า 0; } MEMORY MAP สำหรับข้างต้น: data text bss dec hex ชื่อไฟล์ 7264 1688 1040 9992 2708 a.exe MEMORY MAP สำหรับ 2: data data bss dec hex ชื่อไฟล์ hex 7280 1688 1040 10008 2718 a.exe MEMORY MAP สำหรับ 3: data data bss dec hex ชื่อไฟล์ 7280 1688 1040 1,0008 2718 a.exe
Mahori

124

สำหรับผู้เยี่ยมชมในอนาคตที่อาจสนใจรู้เกี่ยวกับเซ็กเมนต์หน่วยความจำเหล่านั้นฉันกำลังเขียนจุดสำคัญเกี่ยวกับเซกเมนต์หน่วยความจำ 5 ส่วนใน C:

บางหัวขึ้น:

  1. เมื่อใดก็ตามที่โปรแกรม C ถูกดำเนินการหน่วยความจำบางส่วนจะถูกจัดสรรใน RAM สำหรับการดำเนินการโปรแกรม หน่วยความจำนี้ใช้สำหรับจัดเก็บรหัสที่เรียกใช้บ่อย (ข้อมูลไบนารี) ตัวแปรโปรแกรม ฯลฯ ส่วนหน่วยความจำด้านล่างพูดถึงสิ่งเดียวกัน:
  2. โดยทั่วไปแล้วจะมีตัวแปรสามประเภท:
    • ตัวแปรท้องถิ่น (เรียกอีกอย่างว่าตัวแปรอัตโนมัติใน C)
    • ตัวแปรทั่วโลก
    • ตัวแปรแบบคงที่
    • คุณสามารถมีตัวแปรโกลบอลสแตติกหรือสแตติกท้องถิ่น แต่สามตัวแปรข้างต้นเป็นประเภทผู้ปกครอง

5 ส่วนหน่วยความจำใน C:

1. ส่วนของรหัส

  • เซ็กเมนต์รหัสหรือที่เรียกว่าเซ็กเมนต์ข้อความคือพื้นที่ของหน่วยความจำซึ่งมีรหัสที่เรียกใช้บ่อย
  • ส่วนของรหัสนั้นมักจะเป็นแบบอ่านอย่างเดียวเพื่อหลีกเลี่ยงความเสี่ยงที่จะถูกเขียนทับโดยการเขียนโปรแกรมบั๊กเช่น buffer-overflow ฯลฯ
  • ส่วนรหัสไม่มีตัวแปรของโปรแกรมเช่นตัวแปรโลคัล ( เรียกอีกอย่างว่าตัวแปรอัตโนมัติใน C ), ตัวแปรทั่วโลก ฯลฯ
  • ขึ้นอยู่กับการใช้งาน C ส่วนรหัสยังสามารถมีตัวอักษรสตริงแบบอ่านอย่างเดียว ตัวอย่างเช่นเมื่อคุณทำprintf("Hello, world")สตริง "Hello, world" จะถูกสร้างขึ้นในส่วนของรหัส / ข้อความ คุณสามารถตรวจสอบได้โดยใช้sizeคำสั่งใน Linux OS
  • อ่านเพิ่มเติม

ส่วนข้อมูล

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

2. ส่วนข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้น

  • ส่วนนี้เรียกอีกอย่างว่าbss bss
  • นี่คือส่วนของหน่วยความจำที่มี:
    1. ตัวแปรโกลบอลแบบไม่กำหนดค่าเริ่มต้น (รวมถึงตัวแปรพอยน์เตอร์)
    2. ตัวแปรโกลบอลคงที่แบบไม่กำหนดค่าเริ่มต้น
    3. ตัวแปรสแตติกท้องถิ่นที่ไม่กำหนดค่าเริ่มต้น
  • ตัวแปรโลคัลหรือโลคัลแบบสแตติกใด ๆ ที่ไม่ได้ถูกเตรียมข้อมูลเบื้องต้นจะถูกเก็บไว้ในเซ็กเมนต์ข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้น
  • ตัวอย่างเช่น: ตัวแปรกลางint globalVar;หรือตัวแปรโลคัลสแตติกstatic int localStatic;จะถูกเก็บไว้ในส่วนข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้น
  • หากคุณประกาศตัวแปรโกลบอลและกำหนดค่าเริ่มต้นเป็น0หรือNULLจากนั้นก็จะไปยังส่วนข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้นหรือ bss
  • อ่านเพิ่มเติม

3. ส่วนเริ่มต้นของข้อมูล

  • กลุ่มนี้จัดเก็บ:
    1. เริ่มต้นตัวแปรส่วนกลาง (รวมถึงตัวแปรตัวชี้)
    2. เริ่มต้นตัวแปรส่วนกลางคงที่เริ่มต้นตัวแปรทั่วโลกอย่างต่อเนื่อง
    3. เริ่มต้นตัวแปรคงที่ในท้องถิ่น
  • ตัวอย่างเช่น: ตัวแปรโกลบอลint globalVar = 1;หรือตัวแปรโลคัลสแตติกstatic int localStatic = 1;จะถูกเก็บไว้ในส่วนของข้อมูลเริ่มต้น
  • ส่วนนี้สามารถแยกลงไปในพื้นที่อ่านอย่างเดียวที่เริ่มและเตรียมใช้พื้นที่อ่านเขียน เริ่มต้นตัวแปรทั่วโลกคงที่จะไปในพื้นที่อ่านอย่างเดียวที่เริ่มในขณะที่ตัวแปรที่มีค่าสามารถแก้ไขที่รันไทม์จะไปในพื้นที่อ่านเขียนที่เริ่ม
  • ขนาดของส่วนนี้จะถูกกำหนดโดยขนาดของค่าในรหัสที่มาของโปรแกรมและไม่เปลี่ยนแปลงในเวลาทำงาน
  • อ่านเพิ่มเติม

4. กลุ่มสแต็ค

  • Stack เซ็กเมนต์ใช้เพื่อเก็บตัวแปรที่สร้างขึ้นภายในฟังก์ชั่น ( ฟังก์ชั่นอาจเป็นฟังก์ชั่นหลักหรือฟังก์ชั่นที่ผู้ใช้กำหนด ) ตัวแปรเช่น
    1. ตัวแปรท้องถิ่นของฟังก์ชั่น(รวมถึงตัวแปรชี้)
    2. อาร์กิวเมนต์ส่งผ่านไปยังฟังก์ชัน
    3. ที่อยู่ผู้ส่ง
  • ตัวแปรที่จัดเก็บในสแต็กจะถูกลบทันทีที่การทำงานของฟังก์ชันเสร็จสิ้น
  • อ่านเพิ่มเติม

5. ส่วนของกอง

  • ส่วนนี้จะรองรับการจัดสรรหน่วยความจำแบบไดนามิก หากโปรแกรมเมอร์ต้องการที่จะจัดสรรหน่วยความจำบางส่วนแบบไดนามิกใน C แล้วมันจะทำโดยใช้malloc, callocหรือreallocวิธีการ
  • ตัวอย่างเช่นเมื่อint* prt = malloc(sizeof(int) * 2)นั้นแปดไบต์จะถูกจัดสรรในฮีปและที่อยู่หน่วยความจำของตำแหน่งนั้นจะถูกส่งคืนและเก็บไว้ในptrตัวแปร ptrตัวแปรจะเป็นได้ทั้งสแต็คหรือข้อมูลส่วนขึ้นอยู่กับวิธีการที่จะมีการประกาศใช้ /
  • อ่านเพิ่มเติม

ไม่ควรเริ่มต้นแทนการไม่กำหนดค่าเริ่มต้นใน 3 ส่วนของข้อมูลเริ่มต้น
Suraj Jain

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

@PeterMortensen ฉันหมายถึงทั้งสองสิ่ง "ตัวแปรโลคัลหรือตัวแปรโลคัลแบบสแตติกใด ๆ ที่ไม่ได้กำหนดค่าเริ่มต้นจะถูกเก็บไว้ในส่วนข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้น"
hagrawal

เราจะมีตัวแปรคงที่ทั่วโลกใน C ได้อย่างไร?

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

11

แก้ไขประโยคที่ผิดของคุณ

constant data types ----->  code //wrong

ตัวแปรคงที่ในท้องถิ่น -----> สแต็ค

เริ่มต้นตัวแปรคงที่ทั่วโลก -----> ส่วนข้อมูล

ตัวแปรคงที่ทั่วโลกที่ไม่ได้กำหนดค่าเริ่มต้น -----> bss

variables declared and defined in main function  ----->  heap //wrong

ตัวแปรที่ประกาศและกำหนดไว้ในฟังก์ชันหลัก -----> stack

pointers(ex:char *arr,int *arr) ------->  heap //wrong

dynamically allocated space(using malloc,calloc) --------> stack //wrong

พอยน์เตอร์ (เช่น: char * arr, int * arr) -------> ขนาดของตัวแปรตัวชี้นั้นจะอยู่ในสแต็ก

พิจารณาว่าคุณกำลังจัดสรรหน่วยความจำ n ไบต์ (โดยใช้mallocหรือcalloc) แบบไดนามิกแล้วทำให้ตัวแปรตัวชี้ไปยังจุดนั้น ตอนนี้nหน่วยความจำไบต์นั้นอยู่ในฮีปและตัวแปรพอยน์เตอร์ต้องการ 4 ไบต์ (หาก 64 บิตเครื่อง 8 ไบต์) ซึ่งจะอยู่ในสแต็กเพื่อจัดเก็บตัวชี้เริ่มต้นของnไบต์หน่วยความจำ

หมายเหตุ: ตัวแปรตัวชี้สามารถชี้หน่วยความจำของส่วนใดก็ได้

int x = 10;
void func()
{
int a = 0;
int *p = &a: //Now its pointing the memory of stack
int *p2 = &x; //Now its pointing the memory of data segment
chat *name = "ashok" //Now its pointing the constant string literal 
                     //which is actually present in text segment.
char *name2 = malloc(10); //Now its pointing memory in heap
...
}

พื้นที่ที่จัดสรรแบบไดนามิก (โดยใช้ malloc, calloc) --------> heap


พอยน์เตอร์สามารถเป็นได้ทั้งสแต็กหรือฮีป (ดูโดยเฉพาะ: พอยน์เตอร์ต่อพอยน์เตอร์)
เงินฝาก

@airza: อัปเดตทันที โดยทั่วไปฉันกำลังอัปเดตรายละเอียดเท่านั้น :)
rashok

ในแผนที่หน่วยความจำต่อไปนี้คุณช่วยชี้ให้เห็นว่า stack และ heap อยู่ที่ไหน? ฉันไม่แน่ใจว่านี่เป็นคำถามที่ถูกต้องหรือไม่เนื่องจากสแต็คและหน่วยความจำอาจใช้ได้เฉพาะในเวลาทำงาน แผนที่หน่วยความจำ: "data text bss dec ชื่อไฟล์ hex 7280 1688 1040 10008 2718 a.exe"
Mahori

7

สถาปัตยกรรมเดสก์ท็อปที่เป็นที่นิยมแบ่งหน่วยความจำเสมือนของกระบวนการในหลายเซ็กเมนต์ :

  • ส่วนข้อความ: มีรหัสที่ปฏิบัติการได้ ตัวชี้คำสั่งใช้ค่าในช่วงนี้

  • ส่วนข้อมูล: มีตัวแปรทั่วโลก (เช่นวัตถุที่มีการเชื่อมโยงแบบคงที่) แบ่งย่อยเป็นข้อมูลแบบอ่านอย่างเดียว (เช่นค่าคงที่สตริง) และข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้น ("BSS")

  • กลุ่มสแต็ค: มีหน่วยความจำแบบไดนามิกสำหรับโปรแกรมเช่นฟรีสโตร์ ("ฮีป") และสแต็กเฟรมแบบโลคัลสำหรับเธรดทั้งหมด ตามเนื้อผ้า C stack และ C heap เคยเติบโตเป็นเซ็กเมนต์สแต็กจากปลายตรงข้าม แต่ฉันเชื่อว่าการฝึกถูกทอดทิ้งเพราะไม่ปลอดภัยเกินไป

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

บนแพลตฟอร์มอื่นเช่นโหมดจริง x86 เก่าหรือบนอุปกรณ์ฝังตัวสิ่งต่าง ๆ อาจแตกต่างอย่างสิ้นเชิง


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

@SteveJessop: ใช่ฉันก็คิดเช่นกัน แต่มีเธรดอยู่เป็นเวลานาน - ฉันไม่ทราบว่าสแต็คเธรดทั้งหมดจะเติบโตไปข้างหลังหรือไม่หรือหากพวกเขาเติบโตขึ้นเช่นกอง ... ต่อไปทุกวันนี้ทุกอย่างไปในทิศทางเดียวกันและมียาม หน้า
Kerrek SB

6

ฉันหมายถึงตัวแปรเหล่านี้จากมุมมอง C เท่านั้น

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


3

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

  • ตัวแปรที่ไม่สามารถเข้าถึงได้ทั้งหมดสามารถกำจัดได้อย่างสมบูรณ์ - ไม่มีที่เก็บข้อมูล ... ที่ใดก็ได้ ตัวอย่าง - ดูว่ามี42รหัสแอสเซมบลีที่สร้างขึ้น แต่ไม่มีสัญลักษณ์404อย่างไร
  • ตัวแปรที่มีระยะเวลาการเก็บข้อมูลอัตโนมัติที่ไม่ได้ใช้ที่อยู่ไม่จำเป็นต้องเก็บไว้ในหน่วยความจำเลย ตัวอย่างจะเป็นตัวแปรลูป
  • ตัวแปรที่มีconstหรือconstไม่จำเป็นต้องอยู่ในหน่วยความจำ ตัวอย่าง - คอมไพเลอร์สามารถพิสูจน์ได้ว่าfooมีประสิทธิภาพconstและอินไลน์การใช้ลงในรหัส barมีการเชื่อมโยงภายนอกและคอมไพเลอร์ไม่สามารถพิสูจน์ได้ว่ามันจะไม่ถูกเปลี่ยนแปลงนอกโมดูลปัจจุบันดังนั้นจึงไม่ได้รับการ inline
  • วัตถุที่จัดสรรโดยmallocไม่จำเป็นต้องอยู่ในหน่วยความจำที่จัดสรรจากฮีป! ตัวอย่าง - สังเกตว่ารหัสไม่มีการโทรmallocและไม่มีค่า 42 ที่เคยเก็บไว้ในหน่วยความจำมันถูกเก็บไว้ในทะเบียน!
  • ดังนั้นวัตถุที่ได้รับการจัดสรรโดยmallocและการอ้างอิงจะหายไปโดยไม่ต้องจัดสรรคืนวัตถุที่free ไม่จำเป็นต้องรั่วไหลหน่วยความจำ ...
  • วัตถุที่จัดสรรโดยmallocไม่จำเป็นต้องอยู่ภายในฮีปด้านล่างตัวแบ่งโปรแกรม ( sbrk(0)) บน Unixen ...

1

พอยน์เตอร์ (เช่น: char * arr, int * arr) -------> heap

ไม่พวกเขาสามารถอยู่ในสแต็กหรือในส่วนข้อมูล พวกเขาสามารถชี้ไปที่ใดก็ได้


งบเกี่ยวกับmainและตัวแปรที่จัดสรรแบบไดนามิกนั้นผิดเช่นกัน
simonc

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

1
  • ตัวแปร / ตัวแปรอัตโนมัติ ---> ส่วนสแต็ก
  • ตัวแปรที่จัดสรรแบบไดนามิก ---> ส่วนของฮีป
  • เริ่มต้นตัวแปรส่วนกลาง -> ส่วนข้อมูล
  • ตัวแปรโกลบอลแบบไม่กำหนดค่าเริ่มต้น -> ส่วนข้อมูล (bss)
  • ตัวแปรคงที่ -> ส่วนข้อมูล
  • ค่าคงที่สตริง -> ส่วนข้อความ / ส่วนรหัส
  • ฟังก์ชั่น -> ส่วนข้อความ / ส่วนรหัส
  • รหัสข้อความ -> ส่วนข้อความ / ส่วนรหัส
  • รีจิสเตอร์ -> CPU รีจิสเตอร์
  • อินพุตบรรทัดคำสั่ง -> ส่วนของสิ่งแวดล้อม / บรรทัดคำสั่ง
  • ตัวแปรสภาพแวดล้อม -> ส่วนของสิ่งแวดล้อม / บรรทัดคำสั่ง

ส่วนบรรทัดสิ่งแวดล้อม / คำสั่งคืออะไร? มีอยู่ใน Linux หรือไม่
Haoyuan Ge

-1

ตัวอย่าง 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 ทำงานอย่างไร

อย่างไรก็ตามโปรดทราบว่านี่เป็นสิ่งที่execsyscall ทำภายใต้ฮู้ดเมื่อคุณพยายามเรียกใช้ปฏิบัติการ: ทำเครื่องหมายหน้าเว็บที่ต้องการโหลดและเขียนโปรแกรมที่นั่นดูที่: เคอร์เนลรับไบนารีไฟล์ที่ปฏิบัติการได้ ลินุกซ์? ยกเว้นว่า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?

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