C 의 문자열은 결국 '\0' 으로 끝나는 char 배열이다. str 함수들은 전부 이 '\0' 을 믿고 움직인다.C 의 문자열이란?C 에는 string 타입이 따로 없다. 문자를 char 배열에 한 칸씩 넣고, 끝에 '\0' (널 문자)을 붙여서 "여기까지가 문자열"이라고 표시한다. char s[] = "hello"; // 실제로는 'h','e','l','l','o','\0' → 6바이트 그래서 문자열을 담을 공간은 항상 글자 수 + 1 이 필요하다. 이 + 1 을 까먹는 게 문자열 버그의 대부분이다.str 함수들은 크기를 따로 받지 않고 '\0' 이 나올 때까지 계속 읽는다. '\0' 이 없으면 배열 밖까지 계속 읽어버린다. strlensize_t strlen(const char *s); '\0..
문제split_lines() 는 줄 포인터들을 '지역 배열' parts[] 에 모은 뒤, 그 배열의 주소를 LineView.lines 에 담아 돌려준다. 함수가 끝나면 parts[] 가 있던 스택 프레임은 무효가 되고, 이어서 호출되는 warm_stack() 이 그 자리를 다른 값으로 덮는다. 그 뒤 v.lines[i] 를 읽으면 '덮인 쓰레기'를 포인터로 해석해 역참조 → SIGSEGV. (v.lines 자체는 유효한 스택 주소지만, 그 안의 내용이 이미 오염됐다는 점이 함정) https://github.com/yeooonee/Jungle-C-DebuggingLab/blob/main/challenges/07_stack_use_after_return/bug.c Jungle-C-DebuggingLab/ch..
gdb란?실행 중인 C 프로그램을 원하는 지점에서 멈추고, 그 순간의 변수 값, 메모리, 호출 스택을 들여다보는 도구이다. 사용방법gcc 로 컴파일gcc 는 디버그 정보를 실행 파일에 넣는다. C 언어 - GCC 정리gcc란gcc는 .c 파일을 CPU가 실행할 수 있는 파일로 번역하는 프로그램이다. gcc -Wall -g hello.c -o hello # 컴파일./hello # 실행 gcc 는 전처리 → 컴파일 → 어셈블 → 링크를 한 번에 해준다. 에러 종류를skylarcoding.tistory.comgcc -g -O0 -Wall main.c -o main 나는 보통 run → bt → b (에러난 줄) → r (재실행) → n & info locals 로 문제 확인 흐름으로 진행한다. 핵심 ..
문제어셈블리 코드를 C 코드로 복원한 결과, 빈칸 채우기# 어셈블리코드cmpl $0, %edijle .L1movl $1, %edxjmp .L2.L1:movl $0, %edx.L2:movl %edx, %eaxret# C 코드int function(int x) {int y;if ( ____(1) )_____(2);elsey = 0;return ____(3);} 문제풀이%edi : 첫 번째 인자 x (%rdi의 하위 32비트, int 라서 e)%edx : 지역 변수 y 보관용%eax : 반환값 (%rax의 하위 32비트) cmpl $0, %edicmpl : 비교만 하고 결과는 플래그에 남긴다 cmp 는 두 값을 빼보기만 하고 결과는 버리는 명령어이다. 여기서는 x- 0 을 계산한다.결과의 정보 (0인지,..
함수 포인터란?함수 포인터는 함수의 코드가 시작되는 메모리 주소를 저장하는 변수이다.일반 포인터가 변수 데이터의 주소를 담는다면, 함수 포인터는 코드의 주소를 담는다. 프로그램이 실행되면 함수의 기계어 코드도 메모리의 코드 영역에 올라가기 때문에, 함수도 주소를 가지게 된다. int x = 10;int *p = &x; int add(int a, int b){ return a + b; }int (*fp)(int, int) = add; // 함수 포인터 선언 읽는 법int (*fp)(int x, int *p);// (*fp) : fp 는 포인터다// (int x, int *p) : 그 포인터는 int 와 int *를 받는 함수를 가리킨다// 맨 앞 int : 그 함수는 int 를 반환한다. 안쪽에서 바..