890 likes | 1.1k Views
선언과초기화 (DCL). 사이버보안학과 김현성. 제안. DCL00-C 변하지 않는 객체는 const 로 보장해둬라 DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 DCL02-C 시각적으로 구별되는 식별자를 사용하라 DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 DCL04-C 한 번에 여러 변수를 선언하지 마라 DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라
E N D
선언과초기화(DCL) 사이버보안학과 김현성
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
제안 • DCL10-C 가변 인자를 가진 함수에서는 함수 작성자와 함수 사용자 간의 약속이 지켜져야 한다 • DCL11-C 가변 인자 함수와 연관된 타입 문제를 파악하고 있어야 한다 • DCL12-C 불투명한 타입을 사용해 추상 데이터 타입을 구현하라 • DCL13-C 함수에 의해 바뀌지 않을 값에 대한 포인터를 함수의 매개변수로 사용할 때는 const로정의하라 • DCL14-C 여러 컴파일 단위를 거치는 전역 변수 초기화의 순서에 대해서는 어떤 가정도 하지 마라 • DCL15-C 현재 범위를 넘어서까지 사용되지 않을 객체는 static으로 선언하라
규칙 • DCL30-C 객체를선언할 때 적절한 지속공간을 지정하라 • DCL31-C 식별자를 사용하기 전에 먼저 선언하라 • DCL32-C 서로에게 보이는 식별자가 유일한지를 보장하라 • DCL33-C 함수 인자에서 restrict로 지정된소스 포인터와 목적 포인터가 동일한 객체를 참조하지 않게 하라 • DCL34-C 캐시될 수 없는 데이터에는 volatile을 사용하라 • DCL35-C 함수 정의와 맞지 않는 타입으로 함수를 변환하지 마라 • DCL36-C 링크 분류에서 충돌되는 식별자를 선언하지 마라
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
변하지않는 객체는 const로보장해둬라 DCL00-C 부적절한 코드 예 float pi = 3.14159f; float degrees; float radians; /* ... */ radians = degrees * pi / 180; => pi=3.14159f; => pi가 수정되지 못하도록 보호되어야함
변하지않는 객체는 const로보장해둬라 DCL00-C 해결방법 const float pi = 3.14159f; float degrees; float radians; /* ... */ radians = degrees * pi / 180;
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
내부 스코프에서 변수 이름을 재사용하지 마라 개념적 변수 스코프룰 • 전역변수가 사용될 수 있는 범위 내에서 어떤 변수든 중복해서 전역 변수 이름을 사용하면 안된다 • 어떤 블록 안에서 이미 사용되고 있는 변수와 동일한 이름으로 다른 블록에서 선언하면 안된다
내부 스코프에서 변수 이름을 재사용하지 마라 DCL01-C 부적절한코드 예 char msg[100]; charmsg[100]; void report_error(const char *error_msg){ char msg[80]; /* ... */ strncpy(msg, error_msg, sizeof(msg)); return; } int main(void){ char error_msg[80]; /* ... */ report_error(error_msg); /* ... */ } char msg[80]; strncpy(msg, error_msg, sizeof(msg)); => 의도하지 않은값이 복사됨, 버퍼오버플로우
내부 스코프에서 변수 이름을 재사용하지 마라 DCL01-C 해결방법 charsystem_msg[100]; void report_error(const char *error_msg){ char default_msg[80]; /* ... */ if (error_msg) strncpy(system_msg, error_msg, sizeof(system_msg)); else strncpy(system_msg, default_msg, sizeof(system_msg)); return; } int main(void){ char error_msg[80]; /* ... */ report_error(error_msg); /* ... */ }
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
시각적으로 구별되는 식별자를 사용하라 비슷해보이는 식별자 • 1(하나)과 l(소문자엘) • 0(영)과 O(대문자 O) • 2(둘)와 Z(대문자 Z) • 5(다섯)와 S(대문자 S) • 8(여덟)과 B(대문자 B)
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 어썰션(assert) • assert()는 소프트웨어 결점을 찾아 제거하는데 사용되는 진단도구 • If(index<0||index>=size) { printf(“배열 인덱스 범위 오류”); } • assert(index>=0&&index<size); • assert()는 인자값이 0이면 메시지 출력 • assert((index>=0&&index<size)&&”배열 인덱스 범위 오류”);
상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 DCL03-C 부적절한코드 예 structtimer{ unit8_t MODE; unit32_t DATA; unit32_t COUNT; }; int func(void) { assert(offsetof(timer, DATA)==4); } <= offsetof(n,a) n구조체의 a멤버의 바이트 반환 => func()가 호출되어야만 assert실행됨
상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 DCL03-C 해결방법 structtimer{ unit8_t MODE; unit32_t DATA; unit32_t COUNT; }; #if(assert(offsetof(timer, DATA) !=4)) #error “DATA must be at offset 4” #endif => error지시자 사용시 컴파일타임에 어썰션 평가
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
한 번에 여러 변수를 선언하지 마라 DCL04-C 부적절한코드 예 char *src = 0, c = 0; => char*src, char *c => char *src, char c
한 번에 여러 변수를 선언하지 마라 DCL04-C 해결방법 char *src; char *c; => 개별 행으로 변수를 선언
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
코드의 가독성을 높이기 위해 타입 정의를 사용하라 DCL05-C 부적절한코드 예 void (*signal(int, void(*) (int))) (int); => signal() 함수 선언은 이해하기 힘듦
코드의 가독성을 높이기 위해 타입 정의를 사용하라 DCL05-C 해결방법 typedefvoid (*SighandlerType) (int signum); extern SighandlerType signal( int signum, SighandlerType handler ); <= extern 다른소스코드 .c에서 변수나 함수를 현재파일에서 접근하거나 호출할 때 사용
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 상수 • 정수형 상수 • 10 • 0x1C • 부동소수점 상수 • 1.0 • 6.022e+23 • 문자상수 • ‘a’ • ‘\x10’ • 문자리터럴 • “hello, world” • “\n” <= 심볼릭 상수를 통해 적절한 이름을 붙여 코드의 명확성을 제시하는게 좋음 <= const or 열거형 상수 or 객체형 매크로
프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 상수 지정 • const • const unsigned int buffer_size = 256; • 컴파일타임에 정수형 상수가 필요할 때 사용 불가 • 열거형 상수 • enum { max = 15 }; int a[max]; • 객체형매크로 • #define buffer_size 256
프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 DCL06-C 부적절한코드 예 /* ... */ if(age >= 18){ /* 작업진행 */ } else{ /* 다른작업 진행 */ } /* ... */ 18 => 정수 리터럴 18의 의미가 모호함
프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 DCL06-C 해결방법 enum{ ADULT_AGE=18 }; /* ... */ if(age >= ADULT_AGE){ /* 작업진행 */ } else{ /* 다른작업 진행 */ } /* ... */
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
함수 선언 시 적절한 타입 정보를 포함시켜라 DCL07-C 부적절한코드 예 int max(a, b) int a, b; { return a>b ? a : b; } => 매개변수와 변수 선언을 별개로 가짐
함수 선언 시 적절한 타입 정보를 포함시켜라 DCL07-C 해결방법 int max(int a, int b) { return a>b ? a : b; }
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 DCL08-C 부적절한코드 예 코드에서 OUT_STR_LEN이 항상 IN_STR_LEN 보다 두개 커야 하는 관계 enum { IN_STR_LEN=18, OUT_STR_LEN=20 };
상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 DCL08-C 해결방법 enum { IN_STR_LEN=18, OUT_STR_LEN=IN_STR_LEN+2 };
제안 • DCL00-C 변하지않는 객체는 const로보장해둬라 • DCL01-C 내부 스코프에서 변수 이름을 재사용하지 마라 • DCL02-C 시각적으로 구별되는 식별자를 사용하라 • DCL03-C 상수 수식의 값을 테스트할 때 정적 어썰션을 사용하라 • DCL04-C 한 번에 여러 변수를 선언하지 마라 • DCL05-C 코드의 가독성을 높이기 위해 타입 정의를 사용하라 • DCL06-C 프로그램 로직상의 고정적인 값을 나타낼 때는 의미 있는 심볼릭 상수를 사용하라 • DCL07-C 함수 선언 시 적절한 타입 정보를 포함시켜라 • DCL08-C 상수 정의에서는 상수 간의 관계가 적절하게 나타나도록 정의하라 • DCL09-C errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라
errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라 에러코드함수 반환 타입 • errno를 반환하는 많은 함수가 반환 타입을 int로 선언하거나에러 상태 값을 반환 • errno_t 타입은 errno에서 찾을 수 있는 값들을 갖고 있는 객체의 타입으로 사용되어야 함 errno: 0 message: Successerrno: 1 message: Operation not permittederrno: 2 message: No such file or directoryerrno: 3 message: No such processerrno: 4 message: Interrupted system callerrno: 5 message: Input/output errorerrno: 6 message: No such device or address…errno: 125 message: Operation canceled
errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라 DCL09-C 부적절한코드 예 int enum { NO_FILE_POS_VALUES = 3 }; int operator(FILE *file,int *width,int *height,int *data_offset) { int file_w; int file_h; int file_o; fpos_t offset; if(file==NULL) {return EINVAL;} errno=0; if(fgetpos(file, &offset)!=0) {return errno;} if(fscanf(file, “%i %i %i”, &file_w, &file_h, &file_o) != NO_FILE_POS_VALUES){ return EIO; } … => 반환형 int not errno_t형 EINVAL errno EIO
errno 에러코드를 반환하는 함수의 반환 타입을 errno_t로 정의하라 DCL09-C 해결방법 #include <errno.h> enum { NO_FILE_POS_VALUES = 3 }; errno_t operator(FILE *file,int *width,int *height,int *data_offset) { int file_w; int file_h; int file_o; fpos_t offset; if(file==NULL) {return EINVAL;} errno=0; if(fgetpos(file, &offset)!=0) {return errno;} if(fscanf(file, “%i %i %i”, &file_w, &file_h, &file_o) != NO_FILE_POS_VALUES){ return EIO; } …
제안 • DCL10-C 가변 인자를 가진 함수에서는 함수 작성자와 함수 사용자 간의 약속이 지켜져야 한다 • DCL11-C 가변 인자 함수와 연관된 타입 문제를 파악하고 있어야 한다 • DCL12-C 불투명한 타입을 사용해 추상 데이터 타입을 구현하라 • DCL13-C 함수에 의해 바뀌지 않을 값에 대한 포인터를 함수의 매개변수로 사용할 때는 const로정의하라 • DCL14-C 여러 컴파일 단위를 거치는 전역 변수 초기화의 순서에 대해서는 어떤 가정도 하지 마라 • DCL15-C 현재 범위를 넘어서까지 사용되지 않을 객체는 static으로 선언하라
가변 인자를 가진 함수에서는 함수 작성자와 함수 사용자 간의 약속이 지켜져야 한다 가변인자 함수 va_list • 원래 C 함수들은 고정된 개수의 인수들을 취함. '가변인자 함수'는 함수가 호출 될 때 마다 인수의 개수를 변경 가능 • 가변인자 함수를 사용하기 위해서는 'stdarg.h' 헤더 파일이 필요 • va_list 형으로 선언 • va_start를 사용해서 va_list 형의 포인터 변수를 인수로써 초기화 • va_arg를 호출함으로써 가변인수들을 엑세스 • va_end를 호출해서 포인터 변수인 인수를 끝냈음을 알림
가변 인자를 가진 함수에서는 함수 작성자와 함수 사용자 간의 약속이 지켜져야 한다 DCL10-C 부적절한코드 예 => 호출 average(1, 3, 6, 4, 1); enum { va_eol = -1 }; unsigned int average(int first, …){ unsigned int count = 0; unsigned int sum = 0; int i = first; va_list args; va_start(args, first); while(i != va_eol){ sum += i; count++; i = va_arg(args, int); } va_end(args); return(count ? (sum / count) : 0); } => 종료값 -1 을 만날 수 없어 스택 에서 값을 계속 이용
가변 인자를 가진 함수에서는 함수 작성자와 함수 사용자 간의 약속이 지켜져야 한다 DCL10-C 해결방법 enum { va_eol = -1 }; unsigned int average(int first, …){ unsigned int count = 0; unsigned int sum = 0; int i = first; va_list args; va_start(args, first); while(i != va_eol){ sum += I; count++; i = va_arg(args, int); } va_end(args); return(count ? (sum / count) : 0); } => 호출시 average(1, 3, 6, 4, 1, -1);
제안 • DCL10-C 가변 인자를 가진 함수에서는 함수 작성자와 함수 사용자 간의 약속이 지켜져야 한다 • DCL11-C 가변 인자 함수와 연관된 타입 문제를 파악하고 있어야 한다 • DCL12-C 불투명한 타입을 사용해 추상 데이터 타입을 구현하라 • DCL13-C 함수에 의해 바뀌지 않을 값에 대한 포인터를 함수의 매개변수로 사용할 때는 const로정의하라 • DCL14-C 여러 컴파일 단위를 거치는 전역 변수 초기화의 순서에 대해서는 어떤 가정도 하지 마라 • DCL15-C 현재 범위를 넘어서까지 사용되지 않을 객체는 static으로 선언하라
가변 인자 함수와 연관된 타입 문제를 파악하고 있어야 한다 가변인자 함수 • 가변 인자 함수의 인자 • 정수형 인자의 경우 int보다 작은 타입의 인자는 int로 승계되고, 그렇지 않은 경우는 unsigned int(4)로 승계됨 • float 타입의 인자는 double(8)로 승계됨
가변 인자 함수와 연관된 타입 문제를 파악하고 있어야 한다 DCL11-C 부적절한코드 예 constchar *error_msg=“Error occurred”; /* ... */ printf(“%s:%d”, 15, error_msg); => 인자의 순서 불일치 오류 => printf()함수는 가변인자 함수로 구현 15: Error occurred
가변 인자 함수와 연관된 타입 문제를 파악하고 있어야 한다 DCL11-C 해결방법 constchar *error_msg=“Error occurred”; /* ... */ printf(“%d:%s”, 15, error_msg);
제안 • DCL10-C 가변 인자를 가진 함수에서는 함수 작성자와 함수 사용자 간의 약속이 지켜져야 한다 • DCL11-C 가변 인자 함수와 연관된 타입 문제를 파악하고 있어야 한다 • DCL12-C 불투명한 타입을 사용해 추상 데이터 타입을 구현하라 • DCL13-C 함수에 의해 바뀌지 않을 값에 대한 포인터를 함수의 매개변수로 사용할 때는 const로정의하라 • DCL14-C 여러 컴파일 단위를 거치는 전역 변수 초기화의 순서에 대해서는 어떤 가정도 하지 마라 • DCL15-C 현재 범위를 넘어서까지 사용되지 않을 객체는 static으로 선언하라
불투명한 타입을 사용해 추상 데이터 타입을 구현하라 DCL12-C 부적절한코드 예 => string_mx는 CERT라이브러리 string_m.h에 정의(사용자에게 멤버노출) 정보은닉,데이터캡슐화 제공불가 struct string_mx{ size_t size; size_t maxsize; unsigned char strtype; char *cstr; } typedef struct string_mx * string_m; /*함수선언*/ extern errno_t strcpy_m(string_m s1, const string_m s2); extern errno_t strcat_m(string_m s1, const string_m s2); /*기타*/
불투명한 타입을 사용해 추상 데이터 타입을 구현하라 DCL12-C 해결방법 • string_mx의 데이터 타입이 외부에서 보이지 않도록 private으로 재구현 => 두개의 헤더파일 생성 (하나는 외부노출, 하나는 관리용 내부 파일) • 외부노출 파일(string_mx 구조체는 내부파일에 제시) struct string_mx; typedef struct string_mx *string_m;
제안 • DCL10-C 가변 인자를 가진 함수에서는 함수 작성자와 함수 사용자 간의 약속이 지켜져야 한다 • DCL11-C 가변 인자 함수와 연관된 타입 문제를 파악하고 있어야 한다 • DCL12-C 불투명한 타입을 사용해 추상 데이터 타입을 구현하라 • DCL13-C 함수에 의해 바뀌지 않을 값에 대한 포인터를 함수의 매개변수로 사용할 때는 const로정의하라 • DCL14-C 여러 컴파일 단위를 거치는 전역 변수 초기화의 순서에 대해서는 어떤 가정도 하지 마라 • DCL15-C 현재 범위를 넘어서까지 사용되지 않을 객체는 static으로 선언하라