재할당()에서 이중 무료 오류가 발생하는 이유는 무엇인가요?

C에서 문자열 바꾸기 함수를 작성하려고 시도했는데, 이 함수는 malloc()을 사용하여 할당된 char *에서 작동합니다. 이 함수는 시작 문자열의 문자가 아닌 문자열을 찾아서 바꾼다는 점에서 약간 다릅니다.

검색 문자열과 바꾸기 문자열의 길이가 같거나 바꾸기 문자열이 검색 문자열보다 짧은 경우 할당된 공간이 충분하기 때문에 이 작업을 수행하는 것은 간단합니다. 재할당()을 사용하려고 하면 더블 프리를 하고 있다는 오류가 발생하는데,재할당()`만 사용하고 있기 때문에 어떻게 하는지 알 수 없습니다.

아마도 약간의 코드가 도움이 될 것입니다:

void strrep(char *input, char *search, char *replace) {
    int searchLen = strlen(search);
    int replaceLen = strlen(replace);
    int delta = replaceLen - searchLen;
    char *find = input;

    while (find = strstr(find, search)) {

        if (delta > 0) {
            realloc(input, strlen(input) + delta);
            find = strstr(input, search);            
        }

        memmove(find + replaceLen, find + searchLen, strlen(input) - (find - input));
        memmove(find, replace, replaceLen);
    }
}

대체된 문자열이 초기 문자열보다 길어지는 인스턴스에서 재할당()을 시도하기 전까지는 프로그램이 작동합니다. (여전히 작동하지만 결과와 함께 오류를 뱉어냅니다).

도움이 된다면 호출 코드는 다음과 같습니다:

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

void strrep(char *input, char *search, char *replace);

int main(void) {
    char *input = malloc(81);

    while ((fgets(input, 81, stdin)) != NULL) {
        strrep(input, "Noel", "Christmas");
    }
}
해결책

일반적으로 사용자가 제공한 버퍼에서 해제 또는 재할당을 수행해서는 안 됩니다. 사용자가 공간을 어디에 할당했는지 알 수 없으므로(모듈 내, 다른 DLL 내) 사용자 버퍼에서 할당 함수를 사용할 수 없습니다.

이제 함수 내에서 재할당을 할 수 없다면 사용자가 결과 문자열 최대 길이를 계산하고 이 한 번의 교체가 발생할 수 있을 만큼 충분한 버퍼를 제공할 수 있도록 한 번만 교체하는 등 함수 동작을 약간 변경해야 합니다.

그런 다음 다른 함수를 만들어 여러 번 바꾸기를 수행할 수 있지만 결과 문자열을 위한 전체 공간을 할당하고 사용자 입력 문자열을 복사해야 합니다. 그런 다음 할당된 문자열을 삭제할 수 있는 방법을 제공해야 합니다.

결과

void  strrep(char *input, char *search, char *replace);
char* strrepm(char *input, char *search, char *replace);
void  strrepmfree(char *input);
해설 (0)

39 m, first off, 미안해요 I& 늦게 했다. 이것은 스택 오버플로 (my first 대답. )

일러주라하셨으니 대해 realloc 을 수행할 수 있는 것으로 지적되고 있다 () 는 메모리의 포인터를 변경할 수 있습니다 '라는 기술입니까 나왔다. 이 경우 인수 &quot string"; 유효하지 않게 됩니다. 심지어 이 재지정하면 댁이라면 변경하십시오 아웃해야 유효범위 일단 함수은 끝난다.

이 질문에 대해 realloc 을 수행할 () 가 OP, 포인터입니다 새로 나왔다 메모리. 반환 값은 어딘가에 저장될 수 있어야 합니다. 일반적으로 이렇게 됩니다.

data *foo = malloc(SIZE * sizeof(data));
data *bar = realloc(foo, NEWSIZE * sizeof(data));

/* Test bar for safety before blowing away foo */
if (bar != NULL)
{
   foo = bar;
   bar = NULL;
}
else
{
   fprintf(stderr, "Crap. Memory error.\n");
   free(foo);
   exit(-1);
}

39 로 can& 티부르 점, 친구들, t 에 대한 입력입니다 이 함수 포인터의 값을 변경하십시오 전달되는. 원하는 대로 지정할 수 있습니다, 하지만 아웃해야 유효범위 끝에 검색하기를 변화가 시작된다. 그 다음 블록, &quot input"; 일단 잘못된 포인터입니다 함수은 완료하는지 수도 있고 아닐 수도 있습니다.

void foobar(char *input, int newlength)
{
   /* Here, I ignore my own advice to save space. Check your return values! */
   input = realloc(input, newlength * sizeof(char));
}

마크 반환하는 함수 포인터를 출력물에는 새로운 이와 관련된 작업을 한다. 그렇게 할 경우, onu 를 사용할 수 있는 요청자에게 포인터를 사용하여 그는 다시는 입력입니다. 그런 경우 반환 값 일치시킵니다 동일한 별색이 연락해야 할 수 있는 두 개의 포인터 () 에 있으며, 오직 그 희망이었네 무료 # 39 점, t 일치시킵니다 don& 슬래시나 입력 프로세스를 소유하고 있는 메모리 포인터입니다 이제 수도 있고 아닐 수도 있습니다. 데레페렌츠링 그는혼자서 세그멘테이션.

연산뿐 포인터입니다 입력에 대해 다음과 같이 사용할 수 있습니다

void foobar(char **input, int newlength)
{
   *input = realloc(*input, newlength * sizeof(char));
}

이 경우 발생할 수 있는 입력 포인터입니다 요청자에게 복제본입니다 복제본임을 여전히, 어딘가 잘못된 됐다.

제 생각에 대해 realloc 을 수행할 때 () 함수를 사용하여 깨끗한 피하기 위해 솔루션 슬라이드에서는 수정하려고 caller& # 39 의 입력입니다. 그냥 내버려 복귀하십시오 버퍼 malloc (), 새, 그리고 이전 여부를 결정할 수 있는 무료 요청자에게 사용한다. 이 때문에 이 할 수 있다는 이점도 요청자에게 렉시한테서 원래 문자열을!

해설 (0)

2 달 반 전에 다른 사람이 늦으면 당에 대해 사과했다. 오 나도 꽤 많은 시간을 보내게 하는 소프트웨어) 을 포함하였다.

39 에 대해 아무도 관심 있는 i&, m 은 원래 설계 또는 명시적으로 메모리 손실이 1 씩 오프하도록 오류:. 그리고 그건 왜 못 받는 상황을 정확히 알려주는 메모리 누수가 무료 연산뿐 오류 (같도다라고, 정확히, 틀렸다니까 확보됨 동일한 메모리 언로드하기 짓밟고 해제된 메모리를 통해 얻을 수 있으며 이미 여러 번 - 후).

39 라고 말하는 자들, 전에 실시하는 분석, I& 동의하는 모든 사용자 인터페이스는 미만임 때문이다. 그러나 이 & # 39 처리할 경우 메모리 누수를 / 짓밟고 문제 및 문서화했습니다 할당할지 memory& # 39, 합니다. # 39, & # 39, OK& 요구 사항, 걸릴 수 있다.

문제는 무엇입니까? 뭐, 걍 패스 () 와 재할당하지 버퍼입니다 () 가 이 지역에 대해 realloc 을 수행할 수 있는 새로운 포인터입니다 콩지름에 - 진실이며당신이 무시하시겠습니까 반환 값. 따라서 가능한 한 것, 그리고 당신이 대해 realloc 을 수행할 () 는 원래 메모리 통과시킬 것을 또 다시 같은 포인터입니다 you& # 39, 정보기술 (it), re 확보됨 두 번 다시 원래 값을 전달할 수 있기 때문에 동일한 메모리. 하지만 이 메모리 누수가 있는지 계속 사용할 뿐 아니라, 존 Downey& 고말은 원래 공간의 - # 39 점을 지적하고, s shot in the dark () 이지만, t # 39 얼마나 심하게 강조하십시오 틀렸다니까 대해 realloc 을 수행할 잘못 doesn& 틀렸다니까 언로드하기. 역시 1 씩 오프하도록 there& s # 39, & # 39 nul 위한 충분한 공간이 없기 때문에 오류가 할당할지 \0& # 39;; 가 있는 구체화하십시오.

메모리 누수 발생 메커니즘을 제공합니다 알려줄 수 없기 때문에 마지막 가치에 대한 요청자에게 구체화하십시오. 너 때문에 원래 문자열을 통해 계속 짓밟고 있는 공간을 마련해 석방된 후, 마치 당신의 코드를 호출하는 코드를 신앙이니라 스페이스 너무 받을 수 있다고 할 수 있기 때문에 무료 연산뿐 오류 또는 메모리 제어 정보는 코어 덤프 또는 avamer 완전히 스크램블됨.

또한 doesn& 코드에서 # 39, & # 39, # 39 Noel& 교체하십니까 포지셔닝합니다 양정치 성장을 막을 수 없다. # 39, & # 39, 함께 조이유 Noel&. 하지만 you& 문자를 찾을 때마다 다른 7 개 추가 됩니다; d # 39 의 노엘 확장하십시오 재장착하여 텍스트 및 정보기술 (it), 드릴링됩니다 등등 (아래) 이 문제를 해결할 수 없습니다 - simple solution 은 아마 내 수정 여부를 확인할 수 있는 대체 문자열을 string 검색을. 문자열 검색 후 계속 대체 건너뛰려면 복귀시킴 놓고 있다. 두 번째 비 사소한 문제를 해결하기 위해 코딩 보유하고 있다.

그래, 내 제안됩니다 개정판이 호출됨 기능은:

char *strrep(char *input, char *search, char *replace) {
    int searchLen = strlen(search);
    int replaceLen = strlen(replace);
    int delta = replaceLen - searchLen;
    char *find = input;

    while ((find = strstr(find, search)) != 0) {
        if (delta > 0) {
            input = realloc(input, strlen(input) + delta + 1);
            find = strstr(input, search);            
        }

        memmove(find + replaceLen, find + searchLen, strlen(input) + 1 - (find - input));
        memmove(find, replace, replaceLen);
    }

    return(input);
}

이 코드는 메모리 할당 오류를 찾을 수 없는 경우 () - 아마도 충돌 (단, 그렇지 않을 경우 메모리 누수가) 대해 realloc 을 수행할 수 없습니다. # 39, & # 39 의 com/go/lrvid4005_ps_kr 스티브야 Maguire& 먹어서나 솔리드로 Code& # 39. 책 내용에 대해 광범위한 조사를 위한 메모리 관리 문제.

해설 (1)

아직 시도해 보지 않았기 때문에 어둠 속에서 한 번만 시도해 보았지만 재 할당을하면 malloc과 매우 유사한 포인터를 반환합니다. 재할당은 필요한 경우 포인터를 이동할 수 있으므로 다음을 수행하지 않으면 잘못된 포인터로 작업 할 가능성이 높습니다:

input = realloc(input, strlen(input) + delta);
해설 (1)

**참고: 코드를 편집하여 HTML 이스케이프 코드를 제거하세요.

C/C++를 사용한 지 오래되었지만, 원래 블록 이후에 메모리에 여유가 있는 경우에만 증가하는 재할당은 메모리 포인터 값을 재사용합니다.

예를 들어, 이것을 생각해 보세요:

(xxxxxxxxxx..........)

포인터가 첫 번째 x를 가리키고, .은 여유 메모리 위치를 의미하며, 변수가 가리키는 메모리 크기를 5바이트씩 늘리면 성공할 것입니다. 물론 블록은 정렬을 위해 특정 크기로 반올림되기 때문에 이것은 단순화된 예시이지만 어쨌든 그렇습니다.

그러나 이후에 10바이트 더 늘리려고 하는데 사용 가능한 메모리가 5바이트밖에 없다면 메모리에서 블록을 이동하고 포인터를 업데이트해야 합니다.

그러나 예제에서는 변수에 대한 포인터가 아니라 문자에 대한 포인터를 함수에 전달하고 있으므로 strrep 함수가 내부적으로 사용 중인 변수를 조정할 수는 있지만, 이는 strrep 함수에 대한 로컬 변수이며 호출 코드에는 원래 포인터 변수 값이 남게 됩니다.

그러나 이 포인터 값은 해제되었습니다.

귀하의 경우 입력이 원인입니다.

하지만 다른 제안을 드리고 싶습니다. 귀하의 경우 입력 변수가 실제로 입력 된 것처럼 보이며, 입력 된 경우 전혀 수정해서는 안됩니다.

따라서 이와 같은 부작용은 추적하기 어려울 수 있으므로 입력 을 변경하지 않고 원하는 작업을 수행 할 수있는 다른 방법을 찾으려고 노력할 것입니다.

해설 (0)

대해 realloc 을 수행할 이즈 스트레인지, 복잡하고 많은 시간이 초당 많은 양의 메모리를 다루는 경우에만 사용해야 합니다. 즉, 여기서 실제로 코드를 더 빠르게 수 있습니다.

나는 볼 수 있는 코드

realloc(bytes, smallerSize);

사용한 협력했습니다 버퍼 크기를 조절할 수 있기 때문에 작다. 약 백만 배 협력했습니다 대해 realloc 을 수행할 수 있도록 했다 하더라도, 그 다음 몇 가지 이유로 조교하실 납기를 단축할 수 있어 좋은 것이라고 제공하십시오 버퍼, 임의의 두 번째로 1/2 배치하십시오 폭락을 새로운 복제본입니다. 나쁜 물건을 들어온넘.

항상 사용하여 반환 값 대해 realloc 을 수행할.

해설 (0)

사용할 수 있는 것으로 보인다.

char *strrep(char *string, const char *search, const char *replace) {
    char *p = strstr(string, search);

    if (p) {
        int occurrence = p - string;
        int stringlength = strlen(string);
        int searchlength = strlen(search);
        int replacelength = strlen(replace);

        if (replacelength > searchlength) {
            string = (char *) realloc(string, strlen(string) 
                + replacelength - searchlength + 1);
        }

        if (replacelength != searchlength) {
            memmove(string + occurrence + replacelength, 
                        string + occurrence + searchlength, 
                        stringlength - occurrence - searchlength + 1);
        }

        strncpy(string + occurrence, replace, replacelength);
    }

    return string;
}

어쨌든, 그것 없이는 빨아들이는 코드) 로 보면 한숨 있나요?

해설 (1)

내 신속시작 힌트.

대신: ' (char , , 검색 입력입니다 챨 챨 복귀시킴)' void 스트로프 종료기: 'void 스트로프 (, , 검색, 챨 &amp 챨 입력입니다 챨 복귀시킴)'

및 투자에 본문: 입력 (input, 스트린 (입력) + 델타), '=' 대해 realloc 을 수행할

일반적으로 함수 () 및 대해 realloc 을 수행할 반군지역 검토완료 인수만 값으로 / 참조입니다 설명:).

해설 (1)