참조로 함수를 복사 할 수는 있지만 segfault를 생성하는 다음 코드에서 무슨 일이 벌어지고 있는지 이해하고 싶습니다.함수 포인터가있는 Memcpy는 segfault로 연결됩니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int return0()
{
return 0;
}
int main()
{
int (*r0c)(void) = malloc(100);
memcpy(r0c, return0, 100);
printf("Address of r0c is: %x\n", r0c);
printf("copied is: %d\n", (*r0c)());
return 0;
}
다음은 내 생각에 작동해야하는 정신 모델입니다.
프로세스가 r0c에 할당 된 메모리를 소유합니다. 우리는 return0에 해당하는 데이터 세그먼트에서 데이터를 복사하고 있으며 복사가 성공적입니다.
함수 포인터를 역 참조하는 것이 함수 포인터가 가리키는 데이터 세그먼트를 호출하는 것과 같다고 생각했습니다. 이 경우 명령어 포인터는 함수 return0에 대한 명령어를 포함하는 r0c에 해당하는 데이터 세그먼트로 이동해야합니다. return0에 해당하는 바이너리 코드는 return0의 주소에 의존하는 임의의 점프 또는 함수 호출을 포함하지 않으므로 0을 반환하고 ip를 복원해야합니다 ... 100 바이트는 함수 포인터로는 충분하고 0xc3은 정상입니다 r0c의 범위 내 (바이트 11에 있음).
왜 세분화 오류입니까? 이것은 C의 함수 포인터의 의미에 대한 오해입니까, 아니면 내가 모르는 자체 수정 코드를 방지하는 보안 기능이 있습니까?
'printf ("r0c의 주소는 : % x \ n", r0c);'잘 정의되지 않았습니다. – chux
뭔가가 전체가 잘 정의되어 있지 않다는 것을 알려줍니다. – HolyBlackCat
먼저 함수 (코드)는 실행 가능으로 표시된 메모리 세그먼트에 상주합니다. 할당 된 데이터는 특히 시스템에서 DEP (데이터 실행 방지)를 사용하는 경우 표시되지 않습니다. 데이터 세그먼트에있는 코드를 실행하려면 해당 데이터를 실행 가능으로 표시하는 방법을 알아야합니다. 두 번째로,'memcpy (r0c, return0, 100); '는 아마도 메모리의 끝에서부터 복사하고있을 것이다. 셋째, 코드를 포함하는 메모리 위치가 액세스로부터 보호 될 가능성이 높습니다. – GreatAndPowerfulOz