2017-02-09 1 views
0

내 수업에서는 C에서 운영 체제 시뮬레이터를 작성해야합니다. 첫 번째 프로젝트는 구성 파일과 메타 데이터 파일 두 개를 읽는 것이 었습니다. 완성 된 코드를 실행하는 첫 번째 시도는 세분화 오류 (나는 이것이 내가 해결했다고 믿는다)로 이끌었다. 이제 fgets 문을 줄 단위로 읽는 데 문제가 있습니다. 모든 행을 읽지 만 행을 읽지 않습니다. 프로세스를 끝낼 때까지 파일을 무한정 읽습니다. while 루프에 printf 문을 써서 읽고있는 내용을 볼 수 있으며 각 줄을 살펴볼 수 있습니다.C에서 줄 단위로 파일을 읽으려고 시도했지만 while 루프가 끝나지 않습니다

int readCfgFile (char *filename, CONFIG *filedata) 
{ 
    char buffer[255], trash[255]; 
    FILE *cfgfile = malloc(sizeof cfgfile); 
    cfgfile = fopen(filename, "r"); // Assumed where segfault was 
    if(!cfgfile) 
    { 
     return -2; // Error opening file 
    } 
    char *schedulingCode = malloc(8); 
    char *logToCode = malloc(200); 
    char *tempLine; // Suggested to me as a fix (the using a separate variable part) 
    fgets(trash, 255, cfgfile); //Trash the first line of the file 
    tempLine = fgets(buffer, 255, cfgfile); 
    while(tempLine != NULL) 
    { 
     sscanf(buffer, "Version/Phase: %d", &filedata->version); 
     sscanf(buffer, "File Path: %s", filedata->metaPath); 
     sscanf(buffer, "CPU Scheduling Code: %s", schedulingCode); 
     sscanf(buffer, "Quantum Time (cycles): %d", &filedata->quantum); 
     sscanf(buffer, "Memory Available (KB): %d", &filedata->memory); 
     sscanf(buffer, "Processor Cycle Time (msec): %d", &filedata->processTime); 
     sscanf(buffer, "I/O Cycle Time (msec): %d", &filedata->ioTime); 
     sscanf(buffer, "Log To: %s", logToCode); 
     sscanf(buffer, "Log File Path: %s", filedata->logPath); 
     tempLine = fgets(buffer, 255, cfgfile); 
     if(tempLine == NULL) 
     { 
      break; 
     } 
     printf("%s\n", buffer); 
    } 

파일은 다음과 같습니다

Start Simulator Configuration File 
Version/Phase: 1.0 
File Path: Test_3.mdf 
CPU Scheduling Code: NONE 
Quantum Time (cycles): 55 
Memory Available (KB): 667 
Processor Cycle Time (msec): 10 
I/O Cycle Time (msec): 20 
Log To: Monitor 
Log File Path: logfile_1.lgf 
End Simulator Configuration File. 

사람이 while 루프가 영원히 계속 유지하는 이유 어떤 생각을 가지고 있습니까?

+0

char * logToCode = malloc (sizeof logToCode); -> char * logToCode = malloc (200);'if (버퍼 == NULL)'->'if (tempLine == NULL) ','char * schedulingCode = malloc (sizeof schedulingCode);'char * schedulingCode = malloc (8);'char * tempLine; ,'FILE * cfgfile = malloc (sizeof cfgfile);'->'FILE * cfgfile; ' – BLUEPIXY

+0

제안 사항을 업데이트했지만 여전히 멈추지 않습니다. Windows의 우분투에서 Bash에 대한 코드를 컴파일하고 실행하는 것에 대해 언급해야 할 것입니다. 파일 포인터의 크기를 할당하지 않으면 분할 오류가 발생합니다. 적어도 나는 그 문제가 어디에 있는지 안다. –

답변

0

루프가 영원히 실행된다고 말하면 printf ("% s \ n", 버퍼) 문에 대한 결과가 계속 표시됩니다. 루프 종료 직전. 무엇이 인쇄되고 있습니까?

sscanf 코드와 독립적으로 루프 논리를 테스트하는 것이 좋습니다. 블록을 따르는 것은 당신이 당신의 sscanfs에 추가하고 점진적으로 거기에서 이동 할 수 있습니다 장소에서 그와 같은 (등 추가 검사가 필요하지 않습니다)

fgets(buffer, 255, cfgfile); // just to skip the first line 
while((tempLine = fgets(buffer, 255, cfgfile)) != NULL) 
{ 
     // all the scanfs to read from tempLine/buffer 
     .. 
} 

로 작동합니다. 주위의 사소한 의견 FILE * cfgfile = malloc (sizeof cfgfile);. fopen을 호출하면 FILE에 대한 포인터가 반환되고 malloc의 cfgfile이 유실 될 것이기 때문에 이것은 필요하지 않습니다. 또한이 코드가 완전한 코드인지 확실하지 않지만 logToCode 및 schedulingCode도 유출됩니다.

+0

파일 포인터를 malloc하지 않으면 segfaults가 발생합니다. 출력은 말 그대로 파일마다 반복됩니다. 그러나 편집 한 동안 제안 된 것처럼 보입니다. 이제 다시 segfaults하지만 그것은 아마도 메타 데이터 파일을 읽는 방법 때문일 것입니다. –

+0

@KeithLara -'fopen (filename, "r")'이'FILE * '을 리턴한다는 것을 알고 있습니까? 'malloc()'을 추가하면 동작이 변경됩니다. 왜냐하면 여기에 게시되지 않은, 정의되지 않은 동작이 있기 때문입니다. 정의되지 않은 동작은 바로 그 동작이며, 다르게 동작합니다. 나는'int a = 1'을 덧붙임으로써 다르게 동작 할 것입니다. 당신이 추가 한'malloc()'은 완전하고 완전히 불필요한 것으로 아무것도 수정하지 않았습니다. 코드를 작성할 때 추측을 지키지 마십시오. 발에서 너 자신을 쏠거야. – alvits

0

안녕하세요! 은 다음과 같은 질문에MCVE이 필요합니다. 또한 을 입력하지 마십시오. 질문을 업데이트하여 코드를 변경하십시오. 그러면 이전의 모든 응답이 유효하지 않게 렌더링되는 질문이 변경됩니다. 새로운 질문을 하시려면 새 질문으로 질문하십시오!


것은
char *tempLine = malloc(sizeof tempLine); // Suggested to me as a fix 

그 수정을 신뢰하지 않습니다. 왜 크기의 char을 가리키는 메모리 블록을 할당해야합니까? 얼마나 이상하지 않은가 ... 코드에서 이처럼 초기화 된 몇 가지 다른 변수가 있으며 추측 작업과 비슷합니다. 당신의 추측 - 작업은 문제를 야기 할 가능성이 있습니다.

tempLine = fgets(buffer, 255, cfgfile);은 그 할당에 대한 포인터를 buffer 또는 NULL으로 덮어 씁니다. 이로 인해 메모리 누수가 발생합니다. 너에게 고쳐 준다고 제안한 사람은 너와 같은 valgrind에 대해 배울 필요가있다. 혹시 쓰레기 입력의 라인에하고자하는 경우

그럼에도 불구하고, 그 더 나은과 같이 중간 버퍼없이 달성 할 것 : 왜 당신이

fscanf(cfgfile, "%*[^\n]"); 
fgetc(cfgfile); 

나는 궁금하다 부동 소수점 데이터를 읽으려면 %d을 사용하는 것으로 보입니까?

sscanf(buffer, "Version/Phase: %d", ... // Version/Phase: 1.0 

내가 filedata->version의 유형을 볼 수 만 있다면,이 오류로이를 확인 할 수있을 것은 ...

당신은이 코드를 업데이트했다고 주장했다, 그러나 나는 업데이트를 볼 수 없습니다 :

tempLine = fgets(buffer, 255, cfgfile); 
if(buffer == NULL) // Even checking to see if buffer was null doesn't work 

이 오류가 여기에, 그것을 식별하기 위해, 당신이 기대하는 것처럼 fgets이 테스트 케이스에서, buffer = NULL;을 할당 할 수있는 방법을 당신이 나에게 보여주고 싶은 :

#include <stdio.h> 
char *fgets_fake(char *b, int b_length, FILE *f) { 
    /* INSERT CODE HERE! */ 
    /* Show me how `fgets` can assign `buffer = NULL;` here */ 
    return b; 
} 
int main(void) { 
    char *buffer = "HELLO WORLD!"; 
    fgets_fake(buffer, 0, 0); 
    printf("Is buffer NULL? %s\n", b ? "no" : "yes"); 
} 

(반품 후)으로 재 할당 될 수 있기 때문에 아마 if (tempLine == NULL)을 의미했을 것입니다.

+0

질문을 변경하지 않았지만 segfault는 원래 문제 였지만이 질문을하기 전에 대답을 찾았습니다. 나는 아직 내 PC에 소스 코드를 업데이 트했습니다. 할당의 일부는 int로 버전 유형을 저장하는 것이 었습니다. 왜 그런지 모르겠습니다. Valgrind는 Windows의 Ubuntu에서 Bash에서 작동하지 않습니다. "tempLine == NULL"로는 문제가 해결되지 않습니다. –

+0

실패한 컴파일 또는 잘못된 ID로 인해 오래된 바이너리가있을 가능성이 큽니다. – Sebivor

관련 문제