0Pricing
C Academy · บทเรียน

พอยน์เตอร์ลอย

อันตรายจากการใช้หลังคืนหน่วยความจำ

พอยน์เตอร์ลอย เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน

พอยน์เตอร์ห้อยคืออะไร

พอยน์เตอร์ห้อยชี้ไปยังหน่วยความจำที่ถูกคืนแล้ว หรือไม่สามารถใช้งานได้อีกต่อไป

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

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *p = malloc(sizeof(int));
    *p = 5;
    printf("%d\n", *p);
    free(p);
    p = NULL;
    return 0;
}

การใช้งานหลังคืนหน่วยความจำ

สาเหตุที่พบบ่อยที่สุดคือการอ่านหรือเขียนผ่านพอยน์เตอร์หลังเรียกใช้ free

บล็อกหน่วยความจำนั้นอาจถูกนำไปใช้กับสิ่งอื่นแล้ว

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *p = malloc(sizeof(int));
    *p = 42;
    free(p);
    /* Reading *p here would be use-after-free. */
    p = NULL;
    printf("avoided use-after-free\n");
    return 0;
}

ตั้งเป็นค่าว่างหลังคืนหน่วยความจำ

การตั้งพอยน์เตอร์เป็น NULL ทันทีหลังคืนหน่วยความจำ จะเปลี่ยนการใช้งานโดยไม่ตั้งใจให้กลายเป็นการหยุดทำงานที่ตรวจพบได้ชัดเจน หรือเป็นการเรียก free(NULL) ที่ไม่ก่ออันตราย

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char *buf = malloc(10);
    buf[0] = 'A';
    free(buf);
    buf = NULL;
    if (buf == NULL) printf("buf is safely null\n");
    return 0;
}

การคืนแอดเดรสของตัวแปรภายใน

การคืนแอดเดรสของตัวแปรภายใน (บนสแตก) ทำให้เกิดพอยน์เตอร์ห้อย เพราะตัวแปรนั้นจะหายไปเมื่อฟังก์ชันคืนค่า

ให้ใช้หน่วยความจำบนฮีป หรือส่งบัฟเฟอร์เข้ามาแทน

#include <stdio.h>
#include <stdlib.h>

int *make_value(int v) {
    int *p = malloc(sizeof(int));
    *p = v;
    return p;
}

int main(void) {
    int *p = make_value(99);
    printf("%d\n", *p);
    free(p);
    return 0;
}

พอยน์เตอร์หลายตัวชี้บล็อกเดียวกัน

หากพอยน์เตอร์สองตัวอ้างถึงบล็อกเดียวกัน การคืนหน่วยความจำผ่านตัวหนึ่งจะทำให้อีกตัวกลายเป็นพอยน์เตอร์ห้อย

ให้ติดตามสิทธิ์ความเป็นเจ้าของ เพื่อให้มีเพียงเจ้าของเท่านั้นที่คืนหน่วยความจำ

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *a = malloc(sizeof(int));
    *a = 7;
    int *b = a;
    printf("%d\n", *b);
    free(a);
    a = NULL;
    b = NULL;
    printf("both nulled\n");
    return 0;
}

พอยน์เตอร์ห้อยหลัง realloc

เมื่อ realloc ย้ายบล็อก พอยน์เตอร์เก่าที่ชี้ไปยังตำแหน่งเดิมจะกลายเป็นพอยน์เตอร์ห้อย

ให้ใช้เฉพาะพอยน์เตอร์ที่ realloc คืนมา

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *a = malloc(sizeof(int));
    a[0] = 1;
    int *b = realloc(a, 50 * sizeof(int));
    /* a may now be dangling; use only b. */
    b[0] = 2;
    printf("%d\n", b[0]);
    free(b);
    return 0;
}

การคืนหน่วยความจำในฟังก์ชันช่วย

หากฟังก์ชันช่วยคืนบล็อกหน่วยความจำ พอยน์เตอร์ของฟังก์ชันผู้เรียกจะกลายเป็นพอยน์เตอร์ห้อย ให้ตั้งค่าเป็นค่าว่างหลังการเรียก หรือออกแบบฟังก์ชันช่วยให้รับพอยน์เตอร์ไปยังพอยน์เตอร์

#include <stdio.h>
#include <stdlib.h>

void destroy(int **p) {
    free(*p);
    *p = NULL;
}

int main(void) {
    int *p = malloc(sizeof(int));
    *p = 5;
    destroy(&p);
    printf("p is %s\n", p == NULL ? "null" : "set");
    return 0;
}

เหตุใดจึงอันตราย

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

พอยน์เตอร์ห้อยตามขอบเขต

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

#include <stdio.h>

int main(void) {
    int *p;
    {
        int x = 10;
        p = &x;
        printf("in scope: %d\n", *p);
    }
    /* p now dangles; do not dereference it here. */
    printf("block ended\n");
    return 0;
}

การตรวจหาพอยน์เตอร์ห้อย

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

ให้สร้างโปรแกรมพร้อมเครื่องมือตรวจสอบหน่วยความจำระหว่างการพัฒนา

สรุปวงจรการใช้งานที่ปลอดภัยในโค้ด

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

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *p = malloc(sizeof(int));
    if (!p) return 1;
    *p = 123;
    printf("%d\n", *p);
    free(p);
    p = NULL;
    return 0;
}

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจเรื่องพอยน์เตอร์ห้อย

สรุป

คุณได้เรียนรู้เกี่ยวกับพอยน์เตอร์ห้อย:

  • พอยน์เตอร์เหล่านี้ชี้ไปยังหน่วยความจำที่ถูกคืนแล้วหรืออยู่นอกขอบเขต การใช้งานจึงมีพฤติกรรมที่ไม่กำหนดไว้
  • หลีกเลี่ยงการคืนแอดเดรสของตัวแปรภายใน และอย่าใช้พอยน์เตอร์หลัง free หรือหลัง realloc ย้ายบล็อก
  • ตั้งพอยน์เตอร์เป็น NULL หลังคืนหน่วยความจำ และติดตามสิทธิ์ความเป็นเจ้าของ
  • ใช้เครื่องมือตรวจสอบหน่วยความจำและ Valgrind เพื่อตรวจหาการใช้งานหน่วยความจำหลังคืนแล้ว

คำถามที่พบบ่อย

บทเรียน “พอยน์เตอร์ลอย” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “พอยน์เตอร์ลอย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “พอยน์เตอร์ลอย”

อันตรายจากการใช้หลังคืนหน่วยความจำ คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “พอยน์เตอร์ลอย” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม

ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. malloc และ free
  2. calloc และ realloc
  3. หน่วยความจำรั่ว
  4. พอยน์เตอร์ลอย
← กลับไปที่ C Academy