การเข้าใจและการแก้ไขข้อผิดพลาด Double Free หรือ Corruption
ด้วย realloc()
ใน C
เมื่อทำงานกับการจัดสรรหน่วยความจำแบบไดนามิกใน C หนึ่งในปัญหาทั่วไปที่โปรแกรมเมอร์เผชิญคือข้อผิดพลาดที่เรียกว่า double free หรือ corruption
ซึ่งมักเกิดขึ้นเมื่อใช้ฟังก์ชันที่เช่น realloc()
ซึ่งมีวัตถุประสงค์เพื่อเปลี่ยนขนาดของหน่วยความจำที่ได้รับการจัดสรรมาก่อน ในโพสต์นี้เราจะสำรวจสาเหตุที่ทำให้เกิดข้อผิดพลาดนี้และวิธีการแก้ไขอย่างมีประสิทธิภาพ
ปัญหา: ข้อผิดพลาด Double Free หรือ Corruption
สาเหตุของข้อผิดพลาดคืออะไร?
โค้ดที่เป็นตัวอย่างด้านล่างนี้แทนฟังก์ชันการแทนที่สตริงที่ใช้ realloc()
เพื่อจัดการหน่วยความจำแบบไดนามิกใน C ถึงแม้ว่ามันจะทำงานได้ในบางเงื่อนไข แต่เมื่อสตริงที่ใช้แทนมีความยาวมากกว่าสตริงที่ค้นหา ผู้ใช่มักจะประสบปัญหา double free หรือ corruption
นี่คือมุมมองที่ใกล้ชิดกับการใช้งานทั่วไป:
void strrep(char *input, char *search, char *replace) {
int searchLen = strlen(search);
int replaceLen = strlen(replace);
int delta = replaceLen - searchLen;
char *find = input;
while (find = strstr(find, search)) {
if (delta > 0) {
realloc(input, strlen(input) + delta);
find = strstr(input, search);
}
memmove(find + replaceLen, find + searchLen, strlen(input) - (find - input));
memmove(find, replace, replaceLen);
}
}
ปัญหาที่สำคัญเกิดขึ้นเมื่อฟังก์ชัน realloc()
ถูกเรียกใช้ในบัฟเฟอร์ที่ผู้ใช้จัดให้ ซึ่งสามารถนำไปสู่ปัญหาการจัดการหน่วยความจำที่อาจเกิดขึ้น เนื่องจากการจัดสรรครั้งแรกของบัฟเฟอร์นี้ไม่เป็นที่รู้จักภายในโค้ดของคุณ
วิธีแก้ไข: แนวทางที่ดีที่สุดในการจัดการหน่วยความจำ
หลีกเลี่ยงการจัดสรรใหม่ในบัฟเฟอร์ที่ผู้ใช้จัดให้
เป็นแนวทางที่ดีที่สุด คุณไม่ควร จัดสรรใหม่ หรือทำการลบบัฟเฟอร์ที่ผู้ใช้จัดให้ในฟังก์ชันของคุณ คุณไม่สามารถจัดการการจัดสรรและการปล่อยหน่วยความจำได้อย่างปลอดภัยสำหรับพื้นที่ที่ถูกจัดสรรจากที่อื่น แทนที่จะทำเช่นนั้นให้พิจารณาแนวทางต่อไปนี้:
1. ปรับแต่งพฤติกรรมฟังก์ชัน
เปลี่ยนฟังก์ชัน strrep()
ให้ทำการแทนที่เพียงครั้งเดียว ผู้ใช้ของฟังก์ชันควรคำนวณค่าความยาวสูงสุดของสตริงที่เกิดขึ้นและจัดเตรียมพื้นที่อย่างเพียงพอ
2. แนะนำฟังก์ชันใหม่สำหรับการแทนที่หลายครั้ง
สร้างฟังก์ชันแยกต่างหากสำหรับจัดการการจัดสรรหน่วยความจำและการทำความสะอาดหากจำเป็นต้องมีการแทนที่หลายครั้ง นี่คือเวอร์ชันที่มีการปรับแต่งจากแนวทางก่อนหน้า:
void strrep(char *input, char *search, char *replace);
char* strrepm(char *input, char *search, char *replace);
void strrepmfree(char *input);
3. ตัวอย่างการใช้งาน
นี่คือวิธีที่คุณสามารถนำฟังก์ชันใหม่มาใช้ได้อย่างมีประสิทธิภาพในขณะที่จัดการหน่วยความจำอย่างปลอดภัย:
strrep()
: จัดการการแทนที่สตริงเดียวและถือว่าบัฟเฟอร์ที่ป้อนเข้ามามีขนาดเพียงพอstrrepm()
: จัดสรรบัฟเฟอร์ใหม่ ทำการแทนที่ทั้งหมดและส่งคืนสตริงใหม่strrepmfree()
: ปล่อยหน่วยความจำที่จัดสรรโดยstrrepm()
หลังการใช้งาน
สรุปประเด็นหลัก
- อย่าจัดสรรใหม่ บัฟเฟอร์ที่ผู้ใช้จัดให้โดยตรงภายในฟังก์ชันของคุณ
- พิจารณาการสร้างฟังก์ชันใหม่สำหรับจัดการการจัดสรรหน่วยความจำเมื่อดำเนินการที่ซับซ้อนมากขึ้น เช่น การแทนที่หลายครั้ง
- ให้วิธีการในการปล่อยหน่วยความจำที่จัดสรรอย่างเหมาะสมเพื่อป้องกันไม่ให้เกิดการรั่วไหลของหน่วยความจำ
บทสรุป
โดยการปฏิบัติตามแนวทางการจัดการหน่วยความจำที่ปลอดภัยและปรับพฤติกรรมฟังก์ชันของคุณอย่างเหมาะสม คุณจะสามารถหลีกเลี่ยงจุดบอดทั่วไปของข้อผิดพลาด double free หรือ corruption
เมื่อใช้ realloc()
ใน C การเข้าใจหลักการเหล่านี้จะช่วยให้คุณเขียนโค้ดที่มีเสถียรภาพและดูแลรักษาง่ายขึ้นในขณะที่จัดการหน่วยความจำแบบไดนามิกได้อย่างเชื่อถือได้