C언어 버그
21 Feb 2023 |
목차
C언어의 위험한 코드를 정리한 문서입니다.
메모리누수, 널 문자열 비교
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int p_equal_flag = 0;
char *p = (char *)malloc(20);
p = "hello\0world\0";
if (strcmp(p, "hello\0wall") == 0) {
p_equal_flag = 1;
}
printf("p : %s\n", p);
printf("p_equal_flag : %d\n", p_equal_flag);
free(p);
return 0;
}
버그
- char *p malloc 진행한 뒤 p에 대입연산자 (=) 로 문자열을 입력.
memcpy(p, "hello\0world\0", 20);
써줘야 함
- strcmp로 문자열을 비교.
- 널문자가 포함된 비교를 진행하기에 for문으로 하나하나 비교하거나
memcmp
를 써야 함. strncmp
또한 길이를 지정한다 하더라도 중간에 널 문자를 만나면 비교를 멈추기 때문에 사용하면 안됨.
- 널문자가 포함된 비교를 진행하기에 for문으로 하나하나 비교하거나
널검사 안한 포인터 사용
#include <string.h>
int get_maxlen(char *str1, char *str2) {
if (strlen(str1) > strlen(str2))
return strlen(str1);
else
return strlen(str2);
}
버그
- 널검사 없이
strlen
함수를 사용함.str1
또는str2
변수가 null 이면strlen
함수에서 segmentation fault 발생.- 포인터를 참조할 때에는 항상 널검사 진행.
- 널검사를 하지않는 위험한 함수임을 주석 또는 doxygen을 통해 사전에 정의. - 외부에서 null 검사가 완료된 검증된 포인터만 사용할 수 있도록 함
- 버그는 아니지만 속도상의 문제
strlen
함수가 총 3번 동작함. 2번 동작하게끔 줄일 수 있음
free 후 널 초기화 미진행
#include <stdlib.h>
struct test_t {
int a;
int b;
};
void initialize_test(struct test_t *p) {
if (p == NULL) return ;
p->a = 0;
p->b = 0;
}
void free_test(struct test_t *p) {
if (p == NULL) return ;
free(p);
}
void func() {
struct test_t *p = (struct test *)malloc(sizeof(struct test));
initialize_test(p);
// code
free_test(p);
initialize_test(p);
}
버그
free
후 NULL 초기화를 하지 않아 이후initialize_test
함수의if (p == NULL)
구문에서 비정상 포인터를 걸러내지 못함.#define nullfree(p) if (p) { free(p); p = NULL; }
처럼 매크로를 free를 재정의해서 사용하면 좋음.
Comments