2017-01-29 1 views
-2

나는 vigenere 암호를 사용하여 메시지를 암호화하고 암호 해독하는 프로그램을 작성했습니다. 암호화 부분을 잘 작동, 문제는 해독 부분입니다 : char * * free() 내 프로그램 충돌을 사용하여 할당 취소 할 때. 할당을 해제하지 않으면 프로그램이 제대로 작동하지만 충돌이 발생하지 않습니다.메모리를 할당 해제하기위한 free 명령을 호출하면 프로그램이 중단됩니다. 왜?

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

int main(void) { 
    int choice, check, error; 
    char ch; 
    printf("What do you want to do?\n" 
      "1...Decode a message that is saved in a ciphertext.txt file.\n" 
      "2...Encode a message and save it in a ciphertext.txt file.\n"); 
    do { 
     error = 0; 
     check = scanf("%d%c", &choice, &ch); 
     if (check != 2 || ch != '\n' || choice < 1 || choice > 2) { 
      printf("Error: Invalid input!\n"); 
      error = 1; 
     } 
     fflush(stdin); 
    } while (error); 
    if (choice == 2) { 
     FILE *fp = fopen("ciphertext.txt", "w+"); 
     char buffer[1000]; 
     char *p, *q, *r; 
     char *encryption_text; 
     char *encrypted; 
     char *decrypted; 
     printf("What are bad characters?\n"); 
     printf("-Everything except A-Z and a-z.\n"); 
     printf("Plaintext: "); 
     gets(buffer); 
     decrypted = (char *)malloc(strlen(buffer)); 
     strcpy(decrypted, buffer); 
     printf("Key: "); 
     gets(buffer); 
     encryption_text = (char *)malloc(strlen(buffer)); 
     strcpy(encryption_text, buffer); 
     encrypted = (char *)malloc(strlen(decrypted)); 
     strcpy(encrypted, decrypted); 
     putchar('\n'); 
     p = decrypted; 
     q = encryption_text; 
     r = encrypted; 
     if (strlen(q) > strlen(p)) { 
      printf("The key has to be shorter or equal length as the plaintext."); 
      return 0; 
     } 
     while (*p != '\0') { 
      if (!(*p >= 'A' && *p <= 'Z') && !(*p >= 'a' && *p <= 'z')) { 
       printf("Bad characters."); 
       return 0; 
      } 
      if (*q == '\0') { 
       q = encryption_text; 
      } else if (!(*q >= 'A' && *q <= 'Z') && !(*q >= 'a' && *q <= 'z')) { 
       printf("Bad characters."); 
       return 0; 
      } 
      if (*p >= 'a' && *p <= 'z') *p -= ' '; 
      if (*q >= 'a' && *q <= 'z') *q -= ' '; 
      *r = (*p - 'A' + *q - 'A') % 26 + 'A'; 
      p++; 
      q++; 
      r++; 
     } 
     printf("Ciphertext: "); 
     puts(encrypted); 
     fputs(encryption_text, fp); 
     fprintf(fp, ";"); 
     fputs(encrypted, fp); 
     free(decrypted); 
     free(encrypted); 
     free(encryption_text); 
     fclose(fp); 
    } else { 
     FILE *fp = fopen("ciphertext.txt", "r+"); 
     char buffer[1000]; 
     char *encryption_text; 
     char *encrypted; 
     char *decrypted; 
     char delimeter[2] = ";"; 
     char *token; 
     char *p, *q, *r; 
     fgets(buffer, 1000, fp); 
     encrypted = (char *)calloc(strlen(buffer) * sizeof(char), sizeof(char)); 
     encryption_text = (char *)calloc(strlen(buffer) * sizeof(char), sizeof(char)); 
     token = strtok(buffer, delimeter); 
     strcpy(encryption_text, token); 
     encrypted = strrchr(buffer, '\0'); 
     if (encrypted != NULL) { 
      strcpy(encrypted, encrypted + 1); 
     } 
     decrypted = (char *)calloc(strlen(buffer) * sizeof(char), sizeof(char)); 
     for (p = decrypted, q = encryption_text, r = encrypted; 
       *r != '\0'; p++, r++, q++) { 
      if (*q == '\0') { 
       q = encryption_text; 
      } 
      *p = (*r - 'A' - (*q - 'A') + 26) % 26 + 'A'; 
     } 
     printf("Plaintext: "); 
     puts(decrypted); 
     printf("Key: "); 
     puts(encryption_text); 
     printf("Ciphertext: "); 
     puts(encrypted); 
     if (decrypted) free(decrypted); 
     if (encrypted) free(encrypted); 
     if (encryption_text) free(encryption_text); 
     fclose(fp); 
    } 
    return 0; 
} 

나는 그것이 충돌 이유를 말해 줄 수 있기를 바랍니다 : 다음은 프로그램 코드입니다. 감사!

+1

'해독 = (숯 *)의 malloc (나 strlen (완충액))'-> ''해독 = (숯 *)의 malloc (나 strlen (버퍼) +1)'모든 대 – BLUEPIXY

+1

동일 다른'malloc' 호출. NUL 종결 자 문자열을위한 공간을 할당하지 않습니다. 메모리 손상이 발생하여 정의되지 않은 동작 (임의의 시점에서의 충돌 포함)이 발생합니다. – kaylum

+0

그러나 버퍼에는 1000 자의 공백이 있으며 해독 된 3 개의 암호화 된 모든 encryption_text는 버퍼보다 ​​짧습니다. 그렇지 않니? –

답변

0

충돌 주된 이유는

encrypted = strrchr(buffer, '\0'); 

이있는 당신은 지역 변수 buffer로 표현 메모리에 encrypted 지점 어딘가하자, 아마 다음 줄입니다. 이것은 스택의 가장 가능성있는 메모리이지만 적어도이 메모리는 malloc/calloc을 통해 할당되지 않았습니다.

나중에 encrypted을 해제하면 free- 운영시 충돌이 발생할 가능성이 높습니다.

BTW : 설명에 언급 된대로 strcpy을 사용할 때 malloc/calloc 문구를 다시 말하십시오. '\0'에 대한 공간이 있어야합니다.

또한 strrchr(buffer, '\0')buffer에 들어있는 문자열의 끝을 가리키는 포인터를 반환합니다. 두 번째 문자열 종료 문자가 있다는 보장이 없기 때문에 '\0'을 사용하여 종료 직후 위치에서 메모리를 복사하는 것이 중요 할 수 있습니다.

encrypted = strrchr(buffer, '\0'); 
     if (encrypted != NULL) { 
      strcpy(encrypted, encrypted + 1); 
     } 
+0

('문자열이 암호화되어 있으면 암호화 됨, 암호화 된 문자열이 + 1)': [strcpy] (http://en.cppreference.com/w/c/string/byte/strcpy) 고마워, 문제는 암호화 된 = strrchr (버퍼, '\ 0'); 나는 암호화 된 임시 char *로 대체 한 다음 temp를 암호화 된 것으로 복사했다. 이제는 작동한다. 버퍼가 암호화 된, 해독 된 및 encryption_text보다 크기 때문에 '\ 0'에 대해 누락 된 공간은 문제가 아닙니다. 그러나 당신을 도와 줘서 고마워. :) –

+0

당신을 진심으로 환영합니다. 어떻게 든 주제를 "닫으려면"답변을 승인 된 것으로 표시하는 것을 잊지 마십시오. –

관련 문제