首页 > 解决方案 > 凯撒密码 - 有条件的跳跃或移动取决于未初始化的值

问题描述

我的学校项目有问题。项目是关于凯撒密码的,程序输入包括消息长度、加密消息、截获不良消息(几个字符是正确的)。程序的输出是一个解密的消息。程序正确解密,但是 Valgrind 的输出有错误。此外,我认为我对输入数据条件的处理不当。

有我的程序:

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

/* One character rotation */
char rotate(char original, int offset){
  char * alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

  if (original >= 'A' && original <= 'Z') {
    return alpha[(original - 'A' + offset) % 52];
  }
  else{
    return alpha[(original - 'a' + 26  + offset) % 52];
  }
}

/* String decoding */
void shift(const char *src, char *dst, int offset){
  for (int i = 0; i < strlen(src); i++) {
    dst[i] = rotate(src[i], offset);
  }
}

void printResult(char * coded, char * tapped, int size) {
  char decoded[size];
  int matchingLetters = 0, max = 0, recording = 0;
  for (int i = 0; i <= 52; i++) {
    shift(coded, decoded, i);

    // Zjisteni poctu matchingLetters pismen
    for (int j = 0; j < size; j++ ) {
      if(tapped[j] == decoded[j])
        matchingLetters++;
    }
    if(matchingLetters >= max){
      recording = i;
      max = matchingLetters;
    }
    matchingLetters = 0;
  }
  shift(coded, decoded, recording);
  printf("%s\n",decoded);
}

/* The main program */
int main(int argc, char *argv[])
{
  int size;

  if (scanf("%d\n", &size) != 1) {
    printf("Error: bad input!\n");
    return 100;
  }

  char coded[size + 1];
  char tapped[size + 1];

  if (scanf("%[a-zA-Z]\n", coded) != 1 || scanf("%[a-zA-Z]\n", tapped) != 1) {
    printf("Error: bad input!\n");
    return 100;
  }

  if (strlen(coded) != size || strlen(tapped) != size) {
    fprintf(stderr, "Error: bad input length!");
    return 101;
  }

  printResult(coded, tapped, size);

  return 0;
}

Valgrind 输出:

==866== Memcheck, a memory error detector
==866== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==866== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==866== Command: src/main
==866== 
==866== Conditional jump or move depends on uninitialised value(s)
==866==    at 0x4C2EDB8: strlen (vg_replace_strmem.c:454)
==866==    by 0x4EA0FA1: puts (ioputs.c:35)
==866==    by 0x400B1D: printResult (main.c:50)
==866==    by 0x400BE7: main (main.c:76)
==866== 
==866== 
==866== HEAP SUMMARY:
==866==     in use at exit: 0 bytes in 0 blocks
==866==   total heap usage: 2 allocs, 2 frees, 8,192 bytes allocated
==866== 
==866== All heap blocks were freed -- no leaks are possible
==866== 
==866== For counts of detected and suppressed errors, rerun with: -v
==866== Use --track-origins=yes to see where uninitialised values come from
==866== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

谢谢你的任何建议。

标签: carraysstringvalgrindcaesar-cipher

解决方案


  1. Shift 不会终止dst已解码),这可能会导致strlen进入其他内存。
  2. Decoded不够大,无法包含字符串终止符。

作为风格说明:

for (int i = 0; i < strlen(src); i++)

对许多 C 程序员来说就像是黑板上的钉子。编译器是否可以清理它并不重要。


推荐阅读