이 정수 포인터 재 할당이 충돌하는 원인은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/207800

  •  03-07-2019
  •  | 
  •  

문제

나는 C를 처음 접 했고이 질문이 있습니다. 다음 코드가 충돌하는 이유 :

int *a = 10;
*a = 100;
도움이 되었습니까?

해결책

프로그램에 할당되지 않은 메모리 위치 0x0000000에 100을 쓰려고하기 때문입니다. 그건,

int *a = 10;

포인터 'A'가 메모리의 위치가 10 인 위치를 가리킨다는 것을 의미하지는 않습니다. 이는 메모리에서 10 (0x0000000A)을 주소로 지적한다는 것을 의미합니다. 그런 다음 해당 주소에 무언가를 쓰고 싶지만 할당되지 않기 때문에 그렇게 할 "권리"가 없습니다.

다음을 시도 할 수 있습니다.

int *a = malloc(sizeof(int));
*a = 100;

이것은 끔찍하게 비효율적이지만 효과가 있습니다. 단일 INT 만 필요하면 더미가 아닌 스택. 32 비트 아키텍처에서 포인터의 길이는 32 비트이며 int도 32 비트 길이이므로 포인터 투 -INT 구조가 차지합니다 (적어도) 8 개의 메모리 공간의 8 바이트 4 대신에 이런 식으로 캐싱 문제조차 언급하지 않았습니다.

다른 팁

포인터를 a에 할당해야합니다 메모리 위치, 임의의 값이 아님 (10).

int cell = 10;
int *a = &cell; // a points to address of cell
*a = 100;       // content of cell changed

보다 내 대답 또 다른 질문에주의를 기울이는 것에 대한 .

Malloc () 사용에 약간의 변화를 제안하고 싶습니다. int에 대한 메모리를 할당하는 데 사용하는 모든 답변. 대신에:

a = malloc(sizeof(int));

변수의 유형을 반복하지 않는 것이 좋습니다. 컴파일러에 의해 알려져 있고 수동으로 반복하면 코드가 더 조밀하게 만들어지고 오류 위험을 도입하기 때문입니다. 나중에 선언을 변경하면 예를 들어

long *a;

할당을 변경하지 않고, 당신은 잘못된 양의 메모리를 할당하게됩니다 (일반적인 경우 32 비트 기계에서 int 그리고 long 종종 같은 크기입니다). IMO, 사용하는 것이 좋습니다.

a = malloc(sizeof *a);

이것은 단순히 "A가 가리키는 유형의 크기"를 의미합니다. int, 물론 정확히 맞습니다. 위와 같이 선언에서 유형을 변경하면이 선이 여전히 정확합니다. 과제의 왼쪽에있는 변수 이름을 변경하면 여전히 위험이 있지만 적어도 더 이상 정보를 불필요하게 반복하지 않습니다.

또한 괄호가 필요하지 않습니다 sizeof 실제 객체 (예 : 변수)에서 사용할 때는 유형 이름 만있는 경우 캐스트 표현식처럼 보입니다. sizeof 함수가 아니라 연산자입니다.

당신은 a에 대한 메모리를 할당 한 적이 없기 때문입니다. 당신은 방금 포인터를 위해 스택 공간을 할당했습니다.

int *a = NULL;

a = malloc (sizeof (int));

if (a != NULL)
{
*a =10;
}

작동합니다.

또는 기존 변수의 주소를 줄 수 있습니다.

int a* = NULL;
int b = 10;

a = &b;

이것은 이제 같은 일을한다는 것을 의미합니다

*a = 100;

B를 == 100으로 설정합니다

이것을 확인하십시오 :http://home.netcom.com/~tjensen/ptr/pointers.pdf

다음 줄,

int *a = 10;

정수에 대한 포인터를 정의합니다 . 당신은 그때 가리키다 메모리 위치에 대한 포인터 A.

다음 줄,

*a = 100;

메모리 위치에 값 100을 a.

문제는:

  1. 당신은 어디에 포인트가 있는지 모릅니다. (메모리 위치의 가치를 모른다 10)
  2. 포인트가 어디에서나, 당신은 아마도 그 가치를 바꾸지 않을 것입니다. 아마도 다른 프로그램/프로세스의 메모리 일 것입니다. 당신은 도둑!

int에 대한 포인터를 선언하기 때문에 초기화 포인터 ~ 10 (주소) 다음이 주소에서 int에 값을 할당하려고합니다. 주소 10의 메모리는 프로세스에 속하지 않으므로 충돌이 발생합니다. 이것은 작동해야합니다 :

int *a;
a = malloc(sizeof(int));
*a = 10;
printf("a=%i\n", *a);
free(a);

이 코드가 컴파일 되나요? 10은 컨버터블이 아닙니다 int *, 당신이 그렇게 캐스팅하지 않는 한 :

int *a = (int *) 10;
*a = 100;

이 경우 10 100을 메모리 주소에 100으로 쓰려고합니다. 일반적으로 유효한 메모리 주소가 아니므로 프로그램이 충돌합니다.

액세스 할 수없는 메모리의 일부에 포인터를 할당하고 해당 메모리 위치에 약간의 값을 할당하기 때문에 충돌이 발생할 수 있습니다.

다음과 같이 쓸 수도 있습니다.

int* a = 10;
*a = 100;

첫 번째 줄의 다른 간격에 주목하십시오. 인기있는 스타일은 아니지만 개인적으로 더 명확하다고 생각합니다. 컴파일러와 정확히 같은 의미를 갖습니다.

그런 다음 큰 소리로 읽으십시오.

"Pointer-to-int 'a' becomes 10"
"Value-pointed-to-by 'a' becomes 100"

실제 값을 대체 :

"Value-pointed-to-by 10 becomes 100"

... 10이 사용할 수있는 메모리를 가리킬 가능성이 없다는 것을 알게됩니다.

문자가있는 포인터에 거의 할당하지 않을 것입니다.

int* ptr = (int*)10;  // You've guessed at a memory address, and probably got it wrong
int* ptr = malloc(sizeof(int)); // OS gives you a memory address at runtime  

나는 몇 가지가있을 것 같아요 매우 절대 메모리 주소를 직접 지정하는 낮은 수준의 작업. 예를 들어 커널 구현?

좋아, 오늘 가장 간단한 설명을하려고 노력하면서, 그것에 대한 자세한 사진을 더 자세히 설명하려고 노력합니다. 괄호를 추가하겠습니다.

(int*) a = 10;
(*a) = 100;

당신은 주소 범위에 4 바이트를 쓰려고 시도합니다 [10-13]. 프로그램의 메모리 레이아웃은 일반적으로 더 높아 지므로 응용 프로그램은 실수로 작동 할 수있는 곳에서 아무것도 덮어 쓰지 않습니다 (.Data, .BSS 및 스택에서). 주소 범위가 할당되지 않았기 때문에 대신 충돌이 발생합니다.

포인터는 메모리 위치를 가리키고 C 정적 유형은 포인터의 유형을 정의합니다. 포인터를 쉽게 무시할 수 있지만. 간단히:

(void*) v = NULL;

여기서 우리는 사물로 나아갑니다. 널 포인터 란 무엇입니까? 주소를 지적하는 것은 단순히 포인터입니다.

포인터에 대한 구조물 유형을 줄 수도 있습니다.

struct Hello {
    int id;
    char* name;
};

...

struct Hello* hello_ptr = malloc(sizeof Hello);
hello_ptr->id = 5;
hello_ptr->name = "Cheery";

좋아, Malloc은 무엇입니까? Malloc은 메모리를 할당하고 할당 된 메모리에 대한 포인터를 반환합니다. 다음 유형의 서명이 있습니다.

void* malloc(size_t size);

보수적 인 쓰레기 수집가가 없다면 메모리가 자동으로 해제되지 않을 가능성이 높습니다. 따라서 방금 할당 한 내용에서 메모리를 다시 사용하려면 다음을 수행해야합니다.

free(hello_ptr);

당신이하는 각 malloc에는 크기 태그가 있으므로 무료 -라우 틴에 대해 지적한 덩어리의 크기를 명시 할 필요가 없습니다.

좋아,하지만 한 가지, 메모리에서 캐릭터 문자열은 어떤 모습입니까? 예를 들어 "기분 좋은"과 비슷합니다. 간단한 답변. 제로 종료 바이트 배열입니다.

0.1.2.3.4.5. 6
C h e e r y \0
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top