2014-09-05 4 views
0

파일로부터 몇 바이트를 읽어 다음 추출 된 코드를 고려하지 :동적 배열은

모두 (데이터 배열 파일과 같은 바이트를 가짐) 부하가 예상 결과를 반환하는 함수 호출
typedef struct A{ 
int size; 
char * dataArray; 
}A 

A load(char* filename, int inSize) 
{ 
    A newA; 
    newA.size = inSize; 
    FILE *filePtr; 
    filePtr = fopen(filename,"rb"); 

    char buff[1]; 
    int i = 0; 

    newA.dataArray = (char*)malloc(sizeof(char) * newA.size); 
    for (i = 0; i < newA.size; i++) 
    { 
     fread(buff, sizeof(char), 1, filePtr); 
     newA.dataArray[i] = buff[0]; 
    } 

    char* copyOfDataArray = (char*)malloc(sizeof(char) * newA.size); 

    for (i = 0; i < newA.size; i++) 
    { 
     fread(buff, sizeof(char), 1, filePtr); 
     copyOfDataArray[i] = newA.dataArray[i]; 
    } 

    newA.dataArray = copyOfDataArray; 
    return newA 
} 

void Initialize() 
{ 
    A first = load("file1", 100); 
    A second = load("file2", 20); 
} 

. 변수 first와 second는 결코 다시 사용되지 않습니다.

그러나 코드 수백 라인의 몇 후 프로그램은 항상 함께 충돌 :

*malloc.c:2451: sYSMALLOC: Assertion '(old_top == (..... failed.* 

충돌은 항상 코드의 같은 라인에서 발생하지만, 그 선이 처음 변수와는 아무 상관이없는, 두 번째 또는 심지어 구조체 A로도.

내 질문은입니다 : '첫 번째'와 '두 번째'를 인스턴스화하고로드하는 방법이 잘못 되었습니까? 그것은로드 기능이 끝난 후 오랫동안 프로그램을 중단 메모리 누수/메모리 오버 플로우의 일종을 일으킬 수 있습니까?

보너스 : 충돌이 다시 발생하면 "file1"과 "file2"를 모두로드하자마자 "file1"만로드하면 충돌이 발생하지 않습니다.

대단히 죄송합니다.

+3

'크기'란 무엇입니까? 두 번째 루프에서 파일을 읽는 중 왜 데이터를 삭제합니까? 왜 한 번에 한 바이트 씩 읽어야합니까? 왜 newA.dataArray 포인터를 덮어 쓰고 (메모리 누수가 생기는가?) –

+2

아, C에서 [malloc의 결과를 캐스팅해서는 안됩니다.] (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). –

+0

함수를 떠날 때 할당 된 메모리를 비우고 있습니까? – Sathish

답변

1

메모리 누수가 있습니다. 새 메모리를 할당하기 전에 newA.dataArray에서 이전에 할당 된 메모리를 해제해야합니다.

요아킴의 말처럼, 읽기 작업은 시간이 많이 걸리고 오버 헤드를 최소화하기 위해 블록 단위로 데이터를 읽어야합니다.

또한 파일 설명자를 닫아야합니다. 그렇지 않으면 곧 고갈됩니다.

+0

newA.dataArray = copyOfDataArray를 수행하기 전에 newA.dataArray를 해제해야합니까? – Nitkov

+1

정확히. C에서는 메모리 관리를 담당하므로주의해야합니다. – vookimedlo

0

이미 다른 사람들이 제시 한 코드에 많은 문제가 있습니다. 아래 사항을 확인하십시오

typedef struct A{ 
int size; 
char * dataArray; 
}A 

A load(char* filename, int inSize) 
{ 
    A newA; 
    newA.size = inSize; 
    FILE *filePtr = NULL ; //Use NULL 
    char buff[1]; //Size of buffer is only 1 ,If needed increase that to copy more at a time 
    int i = 0; 

filePtr = fopen(filename,"rb");  
//Try to check for the filePtr == NULL or not 

newA.dataArray = (char*)malloc(sizeof(char) * newA.size); 
//Same checking should be done here 

for (i = 0; i < size; i++) //What is size 
{ 
    fread(buff, sizeof(char), 1, filePtr); 
    newA.dataArray[i] = char[0]; //What is char[0] 
} 
//instead this you can read the bytes in a single call, use that. 
// fread(buff, sizeof(char), <size to read >, filePtr); 

char* copyOfDataArray = (char*)malloc(sizeof(char) * newA.size); 

for (i = 0; i < size; i++) 
{ 
    fread(buff, sizeof(char), 1, filePtr); 
    copyOfDataArray[i] = newA.dataArray[i]; 
} 

//why reading again once you done above. 
newA.dataArray = copyOfDataArray; 

return newA; //Please check: How you can return a auto variable. 
} 
void Initialize() 
{ 
    A first = load("file1", 100); 
    A second = load("file2", 20); 
} 
+0

newA.dataArray = copyOfDataArray; -> 실제 코드에서 copyOfDataArray가 약간 변경되었습니다. return newA; // 확인하십시오 : 자동 변수를 반환하는 방법. -> 이것이 문제 일 수 있습니다. 더 좋은 방법은 무엇입니까? ; // filePtr == NULL인지 아닌지를 확인해 봅니다 -> 질문을 너무 길게하지 않도록 검사를 제거했습니다. newA.dataArray [i] = char [0]; // char [0] - 무엇을 편집했는지, buffer [0]이어야합니다; // 대신이 함수를 사용하여 단일 호출에서 바이트를 읽을 수 있습니다. // fread (buff, sizeof (char), , filePtr); -> 시도해 보겠습니다 – Nitkov

+0

스레드 안전 코드가 필요하지 않은 경우 전역 변수로 이동할 수 있습니다. 해당 변수를 전역 변수로 선언하기 만하면됩니다. 스레드를 안전하게 사용해야하는 경우 잠금을 사용할 수 있습니다. – pradipta

+0

newA.dataArray [i] = char [0]; // char [0] - 무엇을 편집했는지, buffer [0]이어야합니다 : 여기 버퍼의 크기가 데이터를 저장할만큼 길어야합니다. 코드에서 1입니다. – pradipta