JHH9232 Blog

C언어 버그


|

목차


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;
}

버그

  1. char *p malloc 진행한 뒤 p에 대입연산자 (=) 로 문자열을 입력.
    • memcpy(p, "hello\0world\0", 20); 써줘야 함
  2. strcmp로 문자열을 비교.
    • 널문자가 포함된 비교를 진행하기에 for문으로 하나하나 비교하거나 memcmp를 써야 함.
    • strncmp 또한 길이를 지정한다 하더라도 중간에 널 문자를 만나면 비교를 멈추기 때문에 사용하면 안됨.

널검사 안한 포인터 사용

#include <string.h>

int get_maxlen(char *str1, char *str2) {
	if (strlen(str1) > strlen(str2))
		return strlen(str1);
	else
		return strlen(str2);
}

버그

  1. 널검사 없이 strlen 함수를 사용함.
    • str1 또는 str2 변수가 null 이면 strlen 함수에서 segmentation fault 발생.
    • 포인터를 참조할 때에는 항상 널검사 진행.
    • 널검사를 하지않는 위험한 함수임을 주석 또는 doxygen을 통해 사전에 정의. - 외부에서 null 검사가 완료된 검증된 포인터만 사용할 수 있도록 함
  2. 버그는 아니지만 속도상의 문제
    • 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);
}

버그

  1. free 후 NULL 초기화를 하지 않아 이후 initialize_test 함수의 if (p == NULL) 구문에서 비정상 포인터를 걸러내지 못함.
    • #define nullfree(p) if (p) { free(p); p = NULL; } 처럼 매크로를 free를 재정의해서 사용하면 좋음.

Comments