เรื่องของ Stack และ Heap

วันนี้เป็นอีกวันที่เขียน C อย่างเมามัน และไปงงกับ Error แปลกๆอยู่หลายชั่วโมง เหตุเพราะอยากได้ข้อมูลที่มีพื้นที่ของหน่วยความจำที่ต่อเนื่องกัน ในตอนแรกจึงเลือกใช้ static array สำหรับเก็บค่า ซึ่งตอนหลังก็พบว่าไม่จำเป็นต้องใช้

ลองมาดูตัวอย่างกันดีกว่า

มี function หนึ่ง return ค่า string  หรือถ้าเรียกให้ถูกคือ  address ของหน่วยความจำที่เก็บ string แต่ค่าที่ได้มันกลายเป็นภาษาขยะ ยกตัวอย่างง่ายๆจาก code ด้านล่าง ซึ่งจะ print ตัวอักษร A สิบตัวอักษร

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

char *
get_var()
{
    char x[11];

    memset(x,65 /*A*/,10);
    x[10] = '\0';

    printf("get_var()\n");
    printf("%s\n", x);

    return x;
}

int
main()
{
    char * y;

    y = get_var();

    printf("%s\n", y);

    return 0;
}

หลังจาก compile และ run ได้ค่าแบบนี้

$ gcc x.c -o x
$ ./x
get_var()
AAAAAAAAAA
��Y��do

เมื่อ print ตัวแปร x ใน function get_var() ออกมา มันก็ออกมาอย่างที่ควรจะเป็น แต่พอ ค่าของตัวแปร y ที่อยู่ใน main() ซึ่งรับมาจาก get_var() อีกทีมันดันออกมาเป็นขยะ

คราวนี้ลองมาดูของที่ถูกดูบ้าง

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

char *
get_var()
{
    char * x;
    x = (char *) malloc(11);

    memset(x,65 /*A*/,10);
    x[10] = '\0';

    printf("get_var()\n");
    printf("%s\n", x);

    return x;
}

int
main()
{
    char * y;

    y = get_var();

    printf("%s\n", y);

    free(y);

    return 0;
}

$ gcc x.c -o x
$ ./x
get_var()
AAAAAAAAAA
AAAAAAAAAA

คราวนี้ค่าที่ได้ออกมาถูกต้อง

ในตัวอย่างแรกเวลา compile จะมี warning แบบนี้
x.c:19: warning: function returns address of local variable

ซึ่งถ้าเราไม่ทันสังเกตุ หรือไม่สนใจว่ามันคืออะไร มันก็จะเกิดปัญหาแบบที่ผมเป็น

อธิบายง่ายๆว่า การประกาศตัวแปร char x[11]; ในตัวอย่างแรกนั้น address ของ x จะถูกเก็บอยู่ใน stack ของ get_var() ซึ่งไม่สามารถอ้างถึงได้จาก function อื่น พอ function get_var() return ค่าข้อมูลใน stack ของ get_var() ก็หายหมด ทำให้ค่า address ของหน่วนคว่มจำที่ใน function main() รับมาไม่มีอยู่จริง pointer ก็ไปชี้อะไรมั่วซั่ว เวลา print ออกมาดูทำให้ได้ขยะมาอย่างที่เห็น

วิธีแก้ก็ง่ายๆคือ ใช้ตัวแปรที่เก็บใน Heap

char * x;
x = (char *) malloc(11);

เมื่อ get_var() return address ของหน่วยความจำออกมา function อื่นก็ยังสามารถอ้างถึงได้ แต่เมื่อใช้เสร็จต้องคืน memory โดยใช้คำสั่ง free() ด้วย

About these ads

One thought on “เรื่องของ Stack และ Heap

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Connecting to %s