[C]memchr
memchr함수는 메모리블록안에서 원하는 문자를 바이트 단위로 찾는 함수입니다.
1️⃣ 함수원형
< memchr >
void memchr(const void *ptr, int c, size_t size)
2️⃣ 헤더파일, 반환값
반환값:
조건 반환값(size_t) 찾을시 찾은 문자의 주소 찾지 못할시 0(NULL포인터) 헤더파일: <string.h>
3️⃣ 함수구현
< memchr >
void memchr(const void *ptr, int c, size_t size)
{
unsigned char *pb;
pb = (unsigned char*)ptr;
while (size-- > 0)
{
if (*pb == (unsigned char)c)
return (pb);
}
return (0);
}
4️⃣ 특징 & 주의사항
- strchr함수는 내부적으로 문자열이 ‘\0’인지아닌지 확인하는 과정을 거치게 됩니다. memchr은 그 과정이 없기 때문에 속도면에서 약간 더빠릅니다.
- 찾는 문자를 (int)형으로 받고는 있지만 (unsigned char)형으로 변환하여 1byte씩 메모리를 검사하게 됩니다. 그렇기 때문에 1byte이상의 원소를 가진 메모리블럭이나 문자를 찾는 것은 오류가날 가능성이 큽니다. 그래도 int자료형을 이용하고 싶다면 1byte범위인 0~255의 정수만 사용하는 것이 좋고 추가적으로 0을 찾으면 안됩니다.(엉뚱한 곳의 0을 찾을 가능성이 큽니다)
- size값은 ptr의 크기보다 작아야합니다.
- strchr함수때와 마찬가지로 인자를 const void자료형으로 받지만 반환할때는 const가 없는 void형으로 반환을 합니다. 굳이 const를 붙일 필요가 있을까하는 생각이 들었습니다.
- 3번째 인자값에 음수값을 넣으면 버퍼오버플로우가 발생하여 첫번째인자(ptr)의 크기를 훨씬 넘는 범위까지 계속해서 검사를 하게 될 것입니다.
하지만 대부분의 컴파일러들이 경고메시지를 출력해주지않았고 정상 컴파일 되었습니다.
5️⃣ 코드예시(특이케이스)
1. < size값에 음수를 넣어 버퍼오버플로우가 일어난 경우 >
int main(void)
{
int word[] = {2, 3, 4 , 255, 1, 6};
int *result;
result = k_memchr(word, 9, -2);
printf("word is: ");
for(int i = 0; i < 6; i++)
printf("%d ", word[i]);
printf("\nresult is: ");
for(int i = 0; i < 6; i++)
printf("%d ", temp[i]);
printf("\n");
}
/*---출력---*/
word is: 2 3 4 255 1 6
result is: 524297 524840 36175880 524297 655912 35651592 //윈도우Vscode기준
- 기대값: segmetation fault
- 출력값: 524297 524840 36175880 524297 655912 35651592 (쓰래기값)
- 원인: 3번째 인자에 음수를 넣어 버퍼오버플로우가 일어났지만 찾는문자까지도 word배열의 메모리블럭에서 찾지못함
- 이유: 계속해서 검사를 나아가다가 우연히 9 = 0x09 메모리를 발견하여 쓰래기값의 주소를 반환하게 됬습니다.(윈도우Vscode기준이며 리눅스에서는 segmentation fault를 컴파일시에 표시해주었습니다.)
- 결론: 위의 코드같은경우 printf함수로 직접 확인했기 때문에 오류를 검출해줄 수 있었지만 그렇지 않을경우 쓰래기값의 주소가 반환된 사실을 모를 수 있습니다. 리눅스같은 경우 컴파일 전에 memchr함수의 버퍼오버플로우에 대한 경고메시지를 주지는 않지만 컴파일시 segmentation fault오류를 출력해 주었습니다. 하지만 윈도우의 Vscode에서는 이러한 경고나 오류없이 정상적으로 컴파일 되었습니다. 반드시 음수값이 아닌 ptr배열크기 이하의 값으로 3번째인자(size)의 값을 잡아야 합니다.