문제

나는 과제를 위해 꼬리를 구현하기 위해 노력하고 있습니다. 나는 그것을 올바르게 작동하지만 무작위로 무료로 오류를 받고있는 것 같습니다.

나는 그것을 볼 수 없다. 그것을 패턴으로 추적하는 것은 일관성이있다.

예를 들어 프로그램을 "Tail -24 Test.in"으로 호출하면 여러 실행에서 동일한 줄에서 잘못된 체크섬 오류를 얻을 수 있습니다. 그러나 파일이 다르고 다시 인쇄 할 라인이 다르면 오류없이 돌아올 것입니다.

문제를 추적하는 방법에 대한 아이디어는 몇 시간 동안이 문제를 디버깅하려고 노력했습니다.

불쾌한 코드는 다음과 같습니다.

라인은 char **로 정의되며 malloc은 다음과 같습니다.

lines = (char**) malloc(nlines * sizeof(char *));

void insert_line(char *s, int len){

  printf("\t\tLine Number: %d Putting a %d line into slot: %d\n",processed,len,slot);
  if(processed > numlines -1){//clean up
    free(*(lines+slot));
    *(lines + slot) = NULL;
  }
  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
  strcpy(*(lines+slot),s);
  slot = ++processed % numlines;
}
도움이 되었습니까?

해결책

당신의 일상은 할당 된 라인 버퍼를 넘어 서면 쓰고 있습니다.

라인의 크기는 인수로 전달 된 (예 : "Len")는 아마도 NUL 터미네이터를 포함하지 않을 것입니다. Malloc을 호출하여 선 (예 : "S")을 복사 할 때 String Terminator에 추가 바이트를 할당해야합니다.

 *(lines + slot) = (char *) malloc((len + 1) * sizeof(char));

다른 팁

특정 입력 매개 변수로 문제를 지속적으로 재현 할 수 있다면 다음과 같이 디버깅해야합니다.

  • 먼저 문제를 일으키는 정확한 무료로 디버깅하십시오.
  • 그런 다음 자유롭게 될 메모리가 언제 Malloc'ed되었는지 알아냅니다.
  • 다음으로, 메모리가 malloc'ed가있는 곳으로 디버깅하십시오.
  • 메모리 뷰어에서 할당 된 메모리 블록을 찾으십시오. 블록의 시작과 끝을 모두 주목하십시오. 아마도 a라는 특별한 가치가있을 것입니다 가드 블록 블록 직전과 직후.
  • 이제 메모리가 자유롭게 될 때까지 코드를 진행하십시오. 어느 시점에서 코드는 실수로 가드 블록을 덮어 씁니다. 그것이 불쾌한 진술입니다.

문제는 프로그램의 완전히 다른 부분에있을 수 있습니다. 오류를보고하는 것은이 무료이지만 가드 블록을 덮어 쓰는 코드는 어디에나있을 수 있습니다.

첫 번째 질문은 LEN을 어떻게 계산합니까? 그것은 단지 strlen입니까 아니면 0 터미네이터를위한 공간을 포함합니까? 나는 당신이 당신의 strcpy에서 당신의 할당을 과장하고 있다고 생각합니다. 나쁜 행동은 단어 경계에서 발생하는 경향이 있으며 무작위로 나타납니다. 또한 소스 문자열이 널 종료되었는지 확인하십시오. 당신이 읽기쪽에 실수를했고 그들을 종료하지 않았다면. 그런 다음 strcpy가 무작위로 덮어 질 수 있습니다.

  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
  strcpy(*(lines+slot),s);

아마 시도 :

  lines[slot] = (char *) malloc((len + 1) * sizeof(char));
  if(lines[slot] == NULL) exit(EXIT_FAILURE);
  if(strlen(s) <= len){
    strcpy(lines[slot],s);
  }
  else{
    /* do something else... */
  }

일반적인 형태의 관점에서, 나는 또한 모든 것을 조금 더 읽기 쉽고 따르기 쉽고 오류에 저항하기 위해 몇 가지 문체 변화를 만들도록 권장합니다.

포인터 산술은 유효하고 재미 있지만, 배열 양식을 사용하면 의도가 조금 더 명확하다고 생각합니다.

free(lines[slot]);
lines[slot] = NULL;

대신에

free(*(lines+slot));
*(lines + slot) = NULL;

또한 더 적은 정적을 사용하는 것이 좋습니다. 데이터 구조로 그들을 통과하고 접근자와 뮤지터로 전달하기에 쉽습니다. 행동이 일어나는 곳이 훨씬 더 명확 해집니다.

static int numlines = 0;
void insert_line(char *s, int len){
    int numlines = 5;

디버그하기에 비참한 범위 문제를 도입 할 수있는 곳.

nlines와 numlines가 같은 값을 가지고 있습니까?

insert_line의 발신자가 두 번째 매개 변수의 길이를 전달할 때 후행 NUL을위한 공간을 허용합니까?

나는 그것이 관련되어 있는지 확실하지 않지만이 두 줄은 나에게 의심스러운 것 같습니다.

  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if((lines + slot) == NULL) exit(EXIT_FAILURE);

먼저 Malloc의 반환을 할당합니다 lines[slot] 그리고 당신은 확인합니다 (lines+slot), 후자가 null이라면, 당신은 null 포인터를 불신했습니다!

또한 라인 [슬롯] (귀하의 *(lines+slot))가 null이 아닌 경우 malloc ()의 결과를 할당하면 메모리가 누출됩니다.

나는 가정한다 lines a char*라인 []`및 슬롯은 허용 된 경계 내에 있습니다!

나는이 두 줄에 대한 Remo의 의심에 동의하지만 Remo가 꺼진 접선은 아닙니다. 우리는이 버그를 찾는 것에 대한 크레딧을 공유해야합니다.

*(lines + slot) = some value
if((lines + slot) == NULL) then die
should be
if(*(lines + slot) == NULL) then die
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top