Note/Source Code

[C언어] 문자열 연결하기 ( snprintf / strcat 사용)

스카이데이즈 2025. 9. 16. 17:10
728x90

- 보통 문자열 연결할때 아래와 같이 많이 사용

 

sprintf(ctrlChannels, "%s %d", ctrlChannels, bss_info[i].channel);

여기서 문제가 되는 건 OVERLAPPING_COPY (겹치는 메모리 복사)


1. OVERLAPPING_COPY란?

  • 문자열이나 메모리 조작 함수(sprintf, strcpy, memcpy 등)는 원본 버퍼와 목적지 버퍼가 겹칠 경우 동작이 정의되지 않음(Undefined Behavior) 
  • 즉, 함수가 문자열을 읽고 쓰는 과정에서, 아직 읽지 않은 부분이 덮어써져 버릴 수 있어 예상치 못한 결과가 발생

2. 왜 문제가 생기는가?

sprintf는 ctrlChannels를 출력 버퍼(목적지) 로 사용하면서 동시에 "%s" 포맷 때문에 입력 문자열로도 사용

실행 순서를 살펴보면:

  1. sprintf가 ctrlChannels 안의 문자열을 읽기 시작 (%s 처리).
  2. 동시에 같은 ctrlChannels에 새로운 결과를 쓰기 시작.
  3. 읽는 도중에 데이터가 덮어써지면, 원본 문자열이 깨지고 예상치 못한 값이 저장됨.

즉, sprintf가 문자열을 안전하게 복사하지 못하고 꼬이게 됨


3. 실제 문제 사례

예를 들어 ctrlChannels가 "1" 이라고 할 때:

sprintf(ctrlChannels, "%s %d", ctrlChannels, 6);
  • 기대: "1 6"
  • 실제: 출력 과정에서 "1"을 읽기도 전에 "1 6"이 덮어써져 → 결과가 "6" 같은 잘못된 값이 될 수 있음. (컴파일러, 라이브러리 구현에 따라 다르게 깨질 수도 있음)

4. 안전한 해결 방법

겹치지 않도록 임시 버퍼를 사용해야 합니다.

char tmp[256];
snprintf(tmp, sizeof(tmp), "%s %d", ctrlChannels, bss_info[i].channel);
strncpy(ctrlChannels, tmp, sizeof(ctrlChannels));

혹은 strcat 방식으로 이어붙이기:

char numbuf[32];
snprintf(numbuf, sizeof(numbuf), " %d", bss_info[i].channel);
strncat(ctrlChannels, numbuf, sizeof(ctrlChannels) - strlen(ctrlChannels) - 1);

이렇게 하면 읽기와 쓰기가 겹치지 않아서 안전


 

728x90