스 택 에 분 배 된 배열 (문자열) 을 되 돌려 주지 못 하 는 이 유 를 철저히 알 아 보 세 요.
6128 단어 프로 그래 밍 언어함수.zip배열
최근 에 튜 토리 얼 을 준 비 했 습 니 다. 사례 를 준비 하 는 과정 에서 다음 과 같은 코드 조각 을 준비 하여 해석
http scheme
을 보 여 주 었 습 니 다.#include
#include
#include
char *parse_scheme(const char *url)
{
char *p = strstr(url,"://");
return strndup(url,p-url);
}
int main()
{
const char *url = "http://static.mengkang.net/upload/image/2019/0907/1567834464450406.png";
char *scheme = parse_scheme(url);
printf("%s
",scheme);
free(scheme);
return 0;
}
위 는
strndup
방식 을 통 해 뒤에 도 의존 malloc
했 기 때문에 마지막 에 도 필요 하 다 free
.위 챗 그룹 에서 의 개인 편지 parse_scheme
를 char []
로 되 돌려 줄 수 있 습 니까?스 택 에 있 는 배열 도 문자열 을 저장 할 수 있다 는 것 을 알 고 있 습 니 다. 다음 과 같이 바 꿀 수 있 습 니까?char *parse_scheme(const char *url)
{
char *p = strstr(url,"://");
long l = p - url + 1;
char scheme[l];
strncpy(scheme, url, l-1);
return scheme;
}
대부분의 사람들 은 이렇게 쓰 면 안 된다 는 것 을 알 고 있 습 니 다. 스 택 의 주 소 를 되 돌려 주 었 기 때문에 이 함수 에서 돌아 온 후에 그 스 택 공간의 조작 권 도 풀 렸 습 니 다. 이 주 소 를 다시 사용 할 때 값 은 확실 하지 않 습 니 다.
그럼 우 리 는 오늘 이런 상황 이 발생 한 배후 의 진정한 원 리 를 함께 토론 합 시다.
기초 준비
모든 함수 가 실 행 될 때 함수 파라미터 와 부분 변수 등 을 저장 하기 위해 메모리 가 필요 하기 때문에 모든 함수 에 연속 적 인 메모 리 를 분배 해 야 합 니 다. 이 메모 리 는 함수 의 스 택 프레임 (Stack Frame) 이 라 고 합 니 다.연속 적 인 메모리 주소 이기 때문에 프레임 이 라 고 합 니 다.왜 하나 더 넣 으 라 고 했 어 요?모두 함수 호출 스 택 에 익숙 해 졌 을 것 입 니 다. 왜 함수 호출 스 택 이 라 고 부 릅 니까?다음 표현 식
array_values(explode(",",file_get_contents(...)));
함수 의 실행 순 서 는 가장 안쪽 함수 가 가장 먼저 실 행 된 다음 에 순서대로 바깥쪽 함 수 를 실행 하 는 것 입 니 다.그래서 함수 의 집행 은 스 택 의 데이터 구 조 를 이용 하여 스 택 프레임 이 라 고 합 니 다.
x86_64 cpu 의
레지스터 저장 함수 창고 밑 주소, rbp
레지스터 저장 함수 스 택 상단 주소.실험 하 다.
#include
void foo(void)
{
int i;
printf("%d
", i);
i = 666;
}
int main(void)
{
foo();
foo();
return 0;
}
$gcc -g 2.c
$./a.out
0
666
왜 두 번 째 호출
rsp
함수 출력 결 과 는 모두 지난번 함수 호출 의 할당 입 니까?어 셈 블 리 후의 코드 를 먼저 보 세 요.000000000040052d :
#include
void foo(void)
{
40052d: 55 push %rbp
40052e: 48 89 e5 mov %rsp,%rbp
400531: 48 83 ec 10 sub $0x10,%rsp
int i;
printf("%d
", i);
400535: 8b 45 fc mov -0x4(%rbp),%eax
400538: 89 c6 mov %eax,%esi
40053a: bf 00 06 40 00 mov $0x400600,%edi
40053f: b8 00 00 00 00 mov $0x0,%eax
400544: e8 c7 fe ff ff callq 400410
i = 666;
400549: c7 45 fc 9a 02 00 00 movl $0x29a,-0x4(%rbp)
}
400550: c9 leaveq
400551: c3 retq
0000000000400552 :
int main(void)
{
400552: 55 push %rbp
400553: 48 89 e5 mov %rsp,%rbp
foo();
400556: e8 d2 ff ff ff callq 40052d
foo();
40055b: e8 cd ff ff ff callq 40052d
return 0;
400560: b8 00 00 00 00 mov $0x0,%eax
}
400565: 5d pop %rbp
400566: c3 retq
400567: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
40056e: 00 00
이론 분석
처음
foo
함수 전후foo
함수 에 들 어가 기 전에 foo
에 매개 변수 도 없고 부분 변수 도 없 기 때문에 main 의 스 택 프레임 의 길 이 는 0 이 고 main
와 rbp
가 같다 rsp
.집행 할 때callq 40052d
0x7fffffffe2c0
함 수 를 호출 main
한 후에 실 행 된 다음 줄 코드 의 주 소 를 압축 합 니 다. 64 비트 기계 이 고 주소 8 바이트 이기 때 문 입 니 다.입장 foo
후push %rbp
foo
의 값 을 창고 에 저장 합 니 다. 저 장 된 주소 이기 때문에 8 바이트 를 차지 하기 때문에 함수 rbp
를 초기 화 할 때 foo
mov %rsp,%rbp
rbp
는 이미 원래 의 기초 위 에 rsp
바이트 가 붙 었 기 때문에 16
에서 0x7fffffffe2c0
로 바 뀌 었 다.sub $0x10,%rsp
0x7fffffffe2b0
함수 안의 부분 변 수 는 컴 파일 할 때 foo
바이트 가 예약 되 어 있 기 때문에 16
이 rsp
로 바 뀌 어 마지막 에 실 행 됩 니 다.movl $0x29a,-0x4(%rbp)
0x7fffffffe2a0
을 666
에 두 었 습 니 다. 두 번 째 호출 시 인쇄 0x7fffffffe2ac
의 어 셈 블 리 코드 는 다음 과 같 습 니 다. printf("%d
", i);
400535: 8b 45 fc mov -0x4(%rbp),%eax
400538: 89 c6 mov %eax,%esi
40053a: bf 00 06 40 00 mov $0x400600,%edi
40053f: b8 00 00 00 00 mov $0x0,%eax
400544: e8 c7 fe ff ff callq 400410
이차 진입
i
함수 전후지난번
foo
에 저 장 된 -0x4(%rbp)
과 두 번 째 호출 666
의 foo
값 이 처음 과 같 기 때문에 하나의 주소 입 니 다.그래서 rbp
인쇄 되 었 습 니 다.주제 로 돌아가다
#include
#include
#include
char *parse_scheme(const char *url)
{
char *p = strstr(url,"://");
long l = p - url + 1;
char scheme[l];
strncpy(scheme, url, l-1);
printf("%s
",scheme);
return scheme;
}
int main()
{
const char *url = "http://static.mengkang.net/upload/image/2019/0907/1567834464450406.png";
char *scheme = parse_scheme(url);
printf("%s
",scheme);
return 0;
}
디 버 깅 정 보 는 다음 과 같 습 니 다.
666
에서 돌아 올 때 인쇄 parse_scheme
의 결 과 는 scheme
입 니 다. 그러나 우리 가 호출 http
한 후에 상기 사례 와 마찬가지 로 printf
스 택 에서 나 오고 parse_scheme
스 택 에 들 어가 면 스 택 에 메모리 가 다시 교체 되 기 때문에 인쇄 된 결 과 는 반드시 printf
가 아 닙 니 다.주 몽 강
원문 을 읽다
본 고 는 운 서 지역사회 의 오리지널 내용 으로 허락 없 이 전재 할 수 없다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
셸 스 크 립 트 프로 그래 밍: sed 명령 으로 텍스트 편집red 는 온라인 편집기 의 일종 이다.그것 은 한 줄 의 내용 을 한꺼번에 처리한다.작업 중 에 한 고객 의 요 구 를 만 났 습 니 다. 기본 와 이 파이 의 ssid 이름 은 MAC 주소 의 뒷 6 자 리 를 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.