속도 - realloc 함수




realloc()에 이중 자유 오류가 발생하는 이유는 무엇입니까? (6)

내 빠른 힌트.

대신에:
void strrep(char *input, char *search, char *replace)
시험:
void strrep(char *&input, char *search, char *replace)

그리고 몸에서보다 :
input = realloc(input, strlen(input) + delta);

일반적으로 함수 인수를 값 / 참조 및 realloc () 설명으로 전달하는 방법에 대해 읽습니다.

C에서 malloc() 사용하여 할당 한 char * 에서 작동하는 문자열 대체 함수를 작성하려고했습니다. 시작 문자열에있는 문자가 아니라 문자열을 찾아서 바꿀 수 있다는 점에서 조금 다릅니다.

할당 된 공간이 충분하기 때문에 검색 및 문자열 바꾸기가 동일한 길이 (또는 바꾸기 문자열이 검색 문자열보다 짧으면)하는 것이 쉽습니다. realloc() 을 사용하려고하면 double free를하고 있다는 오류가 발생합니다. realloc() 만 사용하고 있기 때문에 나는 어떻게 보이지 않습니다.

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

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);
    }
}

대체 문자열이 초기 문자열보다 길어질 때 realloc() 을 시도 할 때까지 프로그램이 작동합니다. (그것은 여전히 ​​일종의 작품이며, 결과뿐만 아니라 오류도 뱉어냅니다.)

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

#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");
    }
}

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

input = realloc(input, strlen(input) + delta);

참고, 코드를 편집하여 HTML 이스케이프 코드를 제거하십시오.

음, C / C ++를 사용한 이후로는 오랜 시간이 걸렸지 만 realloc은 원래 블록 다음에 메모리가있을 경우에만 메모리 포인터 값을 재사용합니다.

예를 들어 다음을 고려하십시오.

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

포인터가 첫 번째 x를 가리키는 경우 및. 여유 메모리 위치를 의미하고 변수가 가리키는 메모리 크기가 5 바이트 증가하면 성공할 것입니다. 이것은 블록이 정렬을 위해 특정 크기로 반올림되었지만 어쨌든 단순화 된 예제입니다.

그러나 이후에 다른 10 바이트 씩 늘려서 사용할 수있는 경우 5 개만 사용하면 메모리에서 블록을 이동하고 포인터를 업데이트해야합니다.

그러나 예제에서는 변수에 대한 포인터가 아닌 포인터에 문자에 대한 포인터를 전달하므로 strrep 함수가 내부적으로 변수를 조정할 수는 있지만 strrep 함수에 대한 로컬 변수이며 당신의 호출 코드는 원래 포인터 변수 값으로 남을 것이다.

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

귀하의 경우, 입력은 범인입니다.

그러나 나는 또 다른 제안을 할 것이다. 귀하의 경우에는 입력 변수가 실제로 입력되어있는 것처럼 보이고, 입력 된 경우에는 수정해서는 안됩니다.

따라서 입력 을 변경하지 않고도 원하는 작업을 수행 할 수있는 다른 방법을 찾으려합니다. 이러한 부작용을 추적하기가 어려울 수 있습니다.


realloc은 이상하고 복잡하며 초당 많은 메모리를 처리 할 때만 사용해야합니다. 즉, 실제로 코드를 더 빠르게 만들 수 있습니다.

나는 코드를 보았다.

realloc(bytes, smallerSize);

버퍼가 작아 지도록 버퍼 크기를 조정하기 위해 사용되었습니다. 수백만 번 작업 한 후, 어떤 이유로 realloc은 버퍼를 줄이는 경우에도 새로운 복사본을 얻을 수 있다고 판단했습니다. 그래서 나쁜 일이 일어난 후 1/2 초에 무작위로 충돌합니다.

항상 realloc의 반환 값을 사용하십시오.


우선, 파티에 늦었다면 미안해. 이것은 내 첫 대답이다. :)

지적했듯이, realloc ()이 호출되면 잠재적으로 포인터를 재 할당중인 메모리로 변경할 수 있습니다. 이 경우 "string"인수가 유효하지 않게됩니다. 다시 할당하더라도 기능이 끝나면 변경 내용이 범위를 벗어납니다.

OP에 대답하기 위해 realloc ()은 새로 할당 된 메모리에 대한 포인터를 반환합니다. 반환 값은 어딘가에 저장해야합니다. 일반적으로 다음을 수행합니다.

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);
}

TyBoer가 지적했듯이, 여러분은이 함수의 입력으로 전달되는 포인터의 값을 변경할 수 없습니다. 당신이 원하는 것을 할당 할 수 있지만, 변경은 기능의 끝에서 범위를 벗어날 것입니다. 다음 블록에서 "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));
}

Mark는 새로운 포인터를 함수의 출력으로 반환하여이 문제를 해결하려고합니다. 그렇게하면 입력에 사용한 포인터를 다시 사용하지 않도록 호출자가 수행해야합니다. 반환 값과 일치하면 동일한 지점에 두 포인터가 있으며 그 중 하나에서 free ()를 호출하면됩니다. 일치하지 않으면 입력 포인터가 이제 프로세스가 소유하거나 소유하지 않을 수있는 메모리를 가리 킵니다. 이를 참조 해제하면 분할 오류가 발생할 수 있습니다.

다음과 같이 입력에 대해 이중 포인터를 사용할 수 있습니다.

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

호출자가 입력 포인터의 복제본을 어딘가에 가지고 있으면 복제본이 여전히 유효하지 않을 수 있습니다.

가장 깨끗한 솔루션은 함수 호출자의 입력을 수정할 때 realloc ()을 사용하지 않는 것입니다. 새로운 버퍼를 malloc ()하여 반환하고, 호출자가 이전 텍스트를 해제할지 여부를 결정하게합니다. 발신자가 원래 문자열을 유지하도록하는 이점이 있습니다!


일반적으로, 사용자가 제공 한 버퍼에는 free 또는 realloc을해서는 안됩니다 . 사용자 버퍼에서 할당 함수를 사용할 수 없도록 사용자가 공간을 할당 한 위치 (다른 DLL에서 모듈에 있음)를 알지 못합니다.

함수 내에서 재 할당을 할 수 없다면 하나의 대체 작업 만하는 것처럼 동작을 약간 변경해야하므로 사용자는 결과 문자열 최대 길이를 계산할 수 있고이 버퍼에 대해 충분히 긴 버퍼를 제공 할 수 있습니다 교체가 발생합니다.

그런 다음 여러 대체를 수행하는 다른 함수를 작성할 수 있지만 결과 문자열에 전체 공간을 할당하고 사용자 입력 문자열을 복사해야합니다. 그런 다음 할당 한 문자열을 삭제하는 방법을 제공해야합니다.

를 야기하는:

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




malloc