문제

int main()
{
   char myString = NULL;
   realloc(&myString, 5);
   strncpy((char *)&myString, "test", 5);
}

잘 작동하는 것처럼 보이지만 여전히 스택 대 힙에 대해 약간 혼란스러워합니다. 이것이 허용됩니까? 허용되면, 그렇게합니다 myString 수동으로 풀려야합니까, 아니면 범위를 벗어날 때 해제 될 것입니까?


편집 : 응답에 감사드립니다.

//I want the code to change myString to "tests"
char myString[5] = "test";
realloc(&myString, strlen(myString)+2);
myString[4] = 's';
myString[5] = '\0';
도움이 되었습니까?

해결책

아니요, 이것은 완전히 잘못되었습니다. REALLOC는 Malloc이 할당 한 메모리를 재 할당하는 데만 사용되어야합니다. 우연히 만 일하는 작업은 결국 끔찍하게 충돌합니다.

char *myString = malloc(x);
myString = realloc(myString,y);
free(myString)

그러나 새로 사용하고 삭제하는 것이 좋습니다. 그러나 std :: string을 사용하는 것이 좋습니다.

다른 팁

게시 한 코드에 문제가 있습니다.

  • 예, Malloc, Realloc 및 기타 관련 C 스타일 메모리 할당 함수로 할당하는 모든 것을 자유롭게해야합니다.
  • 나는 당신이 Char가 아닌 Char *mystring을 가지고 있다고 생각합니다. 스택 (char)에있는 무언가의 주소를 전달하는 것은 완전히 잘못된 것입니다.
  • REALLOC에서 사용하기 전에 MyString Char 포인터를 NULL로 초기화해야합니다.
  • 당신은 4를 5가 아닌 strncpy로 전달해야합니다. 더 큰 문자열이 있다면 메모리를 덮어 쓰는 것입니다.
  • 예에서 만든 버퍼를 자유롭게해야합니다.
  • Realloc 호출의 반환 값을 확인해야합니다. realloc ()

REALLOC의 반환 값과 관련하여 :] 0과 같지 않은 크기로 성공적으로 완료되면 Realloc ()는 (아마도 이동) 할당 된 공간에 대한 포인터를 반환합니다. 크기가 0 인 경우, Null 포인터 또는 Free ()로 성공적으로 전달 될 수있는 고유 한 포인터가 반환됩니다. 사용 가능한 메모리가 충분하지 않으면 realloc ()는 널 포인터를 반환하고 errno를 [enomem]으로 설정합니다.

  • realloc은 null을 통과 할 때 Malloc처럼 작동합니다.

PTR이 널 포인터 인 경우 realloc ()는 지정된 크기에 대해 malloc ()처럼 동작합니다.

더 C ++ 방법 :

그래도 이것을 C ++로 태그했으며 C ++의 새로운 연산자를 사용하는 것이 더 안전합니다. 새 연산자는 재 할당을 허용하지 않지만 할당 및 기존 버퍼를 재사용하는 데 작동합니다 (새).

char *myString = new char[5];
strncpy(myString, "test", 4); 
//...
delete[] myString;

또는:

#include <string>

//...

std::string str = "test";

상위 2 개의 인용 소스

이것은 작동하지 않아야합니다. 당신은 처음에는 말로되지 않은 것을 재 할당하고 있습니다. 그리고 아니요, 범위를 벗어날 때 해방되지 않습니다. Malloc 또는 Realloc을 사용할 때는 모두 귀하에게 달려 있습니다.

업데이트 : 편집은 아무것도 바뀌지 않습니다. 처음에는 말이되지 않은 것을 재 할당하려고합니다. 또한 REALLOC의 리턴 값을 무시할 수 없습니다. REALLOC이 다른 곳으로 메모리를 이동 해야하는 경우 반품에서이를 알 수 있습니다. 다시 말해:

char* ptr = malloc(4);
ptr = realloc(ptr, 5);

REALLOC 이후, PTR은 메모리의 완전히 다른 장소를 가리키고 있으며 PTR의 원래 값을 계속 사용하면 자유롭고 생각만큼 크지 않은 메모리를 사용할 수 있습니다.

이것은 위험합니다! 이것은 당신의 스택을 손상시킬 것입니다. Main ()로 돌아온 함수의 스택에 무언가를 재판매하려면 실제로 스택 프레임을 덮어 쓰고 main () 이외의 다른 곳으로 돌아갑니다. 이것은 잠재적 인 보안 구멍입니다.

다음을 실행해보십시오. Realloc에서 충돌하면 운이 좋았습니다. memcpy (& mystring)와 같은 심각한 피해를 입을 수 있습니다.

int dostuff();

int main()
{
        dostuff();
        return 0;
}

int dostuff()
{
        char myString = NULL;
        realloc(&myString, 5);
        strncpy((char *)&myString, "test", 5);
        return 0;
}

이것이 당신이 절대로하지 말아야 할 일입니다. 무료 () 또는 realloc () 스택 변수를 시도하면 스택 변수는 손상된 스택 (예측할 수없는 제어 흐름으로 이어지는), 손상된 힙 서비스 구조, 손상된 사용자 메모리를 포함하여 정의되지 않은 동작으로 이어질 수 있습니다. 프로그램이 AV와 충돌하면 운이 좋다. 어떤 경우에는 효과가있을 수 있지만 결코 그렇게하려고하지 않아야합니다.

경험 규칙 : 메모리 관리자만이 할당 된 메모리 관리자 만 반환합니다. 이 경우 스택 변수를 런타임 힙에 반환하려고 시도하지 마십시오.

귀하의 프로그램은 구문 적으로 유효한 C ++이지만 스택 객체의 주소를 힙 할당으로 전달하기 때문에 정의되지 않은 동작을 생성합니다. 일반적으로 이것은 실행되면 프로그램이 충돌 함을 의미합니다.

스택과 힙은 프로그램을 실행하는 프로세스에 할당 된 두 가지 메모리 영역입니다. 인수와 로컬 변수를 보유하기 위해 함수를 입력하면 스택이 커지고 기능에서 돌아올 때 자동으로 줄어 듭니다. 반면에 힙은 메모리가 주문형으로 얻을 수있는 별도의 주소 영역이며, 더 이상 필요하지 않을 때 명시 적으로 공개되어야합니다.

로컬 변수의 주소가 realloc ()로 전달되면 메모리를 해제하고 다른 곳에 할당하려고 시도 할 수 있습니다. 주소는 힙에서 나오지 않으며 realloc ()가 힙에서 작동하므로 실패합니다. 대부분의 Realloc ()은 주소가 힙에서 제외되고 프로그램을 중단하는 것을 감지 할 것입니다.


이 외에도 예제 프로그램에는 몇 가지 논리적 오류가 포함되어 있습니다.


char myString = NULL;

문자열이 아닌 숯을 잡으라고 변수를 선언합니다. C 스타일 문자열에는 유형이 있습니다 char*, 즉 숯에 대한 포인터.

또한 숯이 할당됩니다 NULL, 주소 제로는 일반적으로 유효하지 않은 포인터에 할당됩니다. 전처리가 대체되므로 컴파일됩니다 NULL 문자 그대로 0. 실제로, 당신은 char에 제로 바이트를 저장합니다. char 컨벤션에 의해 C 스타일 문자열의 터미네이터입니다.


realloc(&myString, 5);

위에서 언급했듯이, 이것은 스택 객체의 주소를 힙 할당 자에게 전달하기 때문에 불법입니다. 이 문제는 두 번째 코드 예제에 남아 있습니다.

또한 반환 값을 버립니다. realloc() 새 메모리가 할당 된 주소를 반환합니다. 이전과 같은 주소가 아닐 수도 있습니다. 심지어는 널 일 수도 있습니다 realloc()당신에게 그것이 기억에서 벗어 났다고 말하는 방법.


strncpy((char *)&myString, "test", 5);

이것은 정확하지만 캐스트는 중복됩니다.


다음은 프로그램의보다 올바른 버전입니다.


#include <stdlib.h>
#include <string.h>

int main()
{
   /* allocate space for, say, one character + terminator */
   char* myString = (char*) malloc(2);

   /* some code using myString omitted */

   /* get more space */
   myString = (char*) realloc(myString, 5);

   /* write to the string */
   strncpy(myString, "test", 5);

   /* free the memory */
   free(myString);

   return 0;
}

C ++에서는 Realloc ()를 완전히 피하는 것이 좋습니다. 예를 들어 다음과 같은 것을 사용할 수 있습니다.


#include <string>

int main()
{
   std::string myString;

   /* some code using myString */

   myString = "test";

   return 0;
}

당신은 자유로울 필요가 없습니다 myString 스택에 있기 때문에 (스코프를 떠날 때 "해제됩니다).

realloc 여기서 불법이므로 주소는 있어야합니다 NULL 또는 이전 전화로 반환 된 주소 realloc, malloc 또는 calloc.

당신이 선언하는 모든 변수는 스택에 있습니다.

int *x;

변수 x 스택에 있습니다! 유형입니다 pointer 주소를 보유합니다.

x = (int *) malloc (sizeof (int));

반환 된 주소를 할당합니다 malloc 변수 x에! 의 내용 x 메모리 주소입니다!

당신이하는 일의 문제는 당신이 가변적이지 않은 무언가에 푹 빠져 있다는 것입니다. 당신은 mystring을 숯으로 정의 했으므로 주소를 변경하려고합니다. 그 나쁜.

realloc () 함수는 전달 된 것을 변경하지 않아야합니다. 힙의 메모리 (또는 이미 할당되지 않은 경우 Null 포인터)에 대한 포인터를 사용하고 힙의 메모리에 대한 포인터를 반환합니다.

따라서 malloc () 또는 realloc () 또는 calloc ()가 할당 한 것에 대한 널 포인터 또는 포인터를 제공하고 반환 된 포인터를 저장합니다.

같은 것

char * myString = NULL;
myString = realloc(myString, 5);

작동하지만 무료 () mystring을 원할 것입니다.

그러나 C ++에서는 std :: string을 사용하십시오.

두 번째 코드 예제에 응답하여 :

예, 이것은 또한 불법입니다. Mystring은 Malloc (또는 Calloc)에 할당되지 않으므로 Realloc으로 재 할당되거나 무료로 해제 될 수 없습니다.

또한 Realloc은 첫 번째 논쟁으로 포인터에 대한 포인터를 사용하지 않습니다. 할당 된 메모리에 대한 포인터가 필요하고 다른 (아마도 다른) 포인터를 반환합니다. 대신 이렇게 전화를 씁니다.

myString = realloc(myString, strlen(myString)+2);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top