为什么 returns 是分段错误(核心已转储)?

Why it returns me segmention fault (core dumbed)?

放两个字符串后,return就是我 segmention fault (core dumbed)

我是运行 gcc 的代码。 Valgrind 写道没有错误。尝试编写使用凯撒法解密文本的代码。首先我输入要解码的文本,第二个文本显示我需要将第一个文本中的字母移动多远。也就是说,选择在接收到的文本和第二个输入的文本之间存在更多字母对应的距离。我仔细检查了一切,对我来说似乎真的没有错误,或者我不熟悉使用内存。

这是例子

输入

xUbbemehbT

XYlloworld

应该return

Helloworld

我真的不明白为什么 return我会这样,这是代码

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

#define INT_MSG_LEN 50;

enum {NO_ERROR = 0, 
      ERROR_INPUT = 100, 
      ERROR_LEN = 101};

static const char *error_texts[] = { "Error input!", 
                                     "Error lenght"};

void shift(char *msgEnc, char *msg, char *msgRes, char *mainMsg, char *alphabet, int offset);
void report_error(int error);
void print_error(int error);
int get_sameletters(char *msg, char *msgRes, int offset);
int get_letter(char letter, char *alphabet);
int compare(char *msgEnc, char *msg, char *msgRes, char *alphabet, int offset);
char *read_Input_Msg(int *msglen);

int main(int argc, char *argv[])
{
    int ret = NO_ERROR;
    char *msgEnc, *msg, *msgRes, *mainMsg, alphabet[53] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int msgEncLen, msgLen;

    msgEnc = msg = msgRes = mainMsg = NULL;
    msgEncLen = msgLen = 0;

    msgEnc = read_Input_Msg(&msgEncLen);
    if (msgEnc)
        msg = read_Input_Msg(&msgLen);

    if (msgEnc == NULL || msg == NULL)
        ret = ERROR_INPUT;
    else if (msgEncLen != msgLen)
        ret = ERROR_LEN;
    
    if (ret == NO_ERROR)
        shift(msgEnc, msg, msgRes, mainMsg, alphabet, msgEncLen);
    else
        print_error(ret);

    free(msgEnc);
    free(msg);
    free(msgRes);
    free(mainMsg);
    return ret;
}

void shift(char *msgEnc, char *msg, char *msgRes, char *mainMsg, char *alphabet, int offset)
{//function for decoding text by a defined offset
    int dis;
    dis = compare(msgEnc, msg, msgRes, alphabet, offset);
    for (int i = 0; i<offset-1; ++i){
        if ((msgEnc[i] >= 'a' && msgEnc[i] <= 'z') || (msgEnc[i] >= 'A' && msgEnc[i] <= 'Z')){
            mainMsg[i] = msgEnc[i+dis];
            break;
        }
    }
    for(int i = 0; i<offset-1; ++i)
        printf("%c", mainMsg[i]);
}

void report_error(int error)
{//prints error 
    if (error >= ERROR_INPUT && error <= ERROR_LEN)
        fprintf(stderr, "%s\n", error_texts[error - ERROR_INPUT]);
}

void print_error(int error)
{//what error it is
    switch (error){
        case ERROR_INPUT:
            report_error(ERROR_INPUT);
            break;
        case ERROR_LEN:
            report_error(ERROR_LEN);
            break;
    }
}

int get_sameletters(char *msg, char *msgRes, int offset)
{//gets count of sameletters between two strings
    int sameLetters = 0;
    for (int i = 0; i<offset-1; ++i){
        if (msg[i] == msgRes[i])
            sameLetters++;
    }
    return sameLetters;
}

int get_letter(char letter, char *alphabet)
{   
    int k;
    for (int i=0; alphabet[i]; ++i){
        if (letter == alphabet[i])
            k = i;
    }
    return k;
}

int compare(char *msgEnc, char *msg, char *msgRes, char *alphabet, int offset)
{//calculate a distance between first input string and string what will get after decryption
    int distance, max = 0;
    for (int i = 0; alphabet[i]; ++i){
        for (int j = 0; msgEnc[j]; ++j){
            if ((msgEnc[i] >= 'a' && msgEnc[i] <= 'z') || (msgEnc[i] >= 'A' && msgEnc[i] <= 'Z'))
                msgRes[j] = alphabet[(get_letter(msgEnc[j], alphabet) + i) % 52];
            }
            int sameLetters = get_sameletters(msg, msgRes, offset);
            if (sameLetters > max){
                max = sameLetters;
                distance = i;
        }
    }
    return distance;
}

char *read_Input_Msg(int *msglen)
{//input messages, at the same time counts the length of the entered string
    int capacity = INT_MSG_LEN;
    char *msg = malloc(capacity);
    int c, len = 0;
    while ((c = getchar()) != EOF && c != '\n'){
        if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
            free(msg);
            msg = NULL;
            len = 0;
            break;
        }
        if (len == capacity){
            char *tmp = realloc(msg, capacity * 2);
            if (tmp == NULL){
                free(msg);
                msg = NULL;
                len = 0;
                break;
            }
            capacity *= 2;
            msg = tmp;
        }
        msg[len++] = c;
    }
    *msglen = len;
    return msg;
}

这是 valgrind 的抱怨,我知道这不是答案,但你的 valgrind 似乎有问题,也许这会有所帮助

==7662== Invalid write of size 1
==7662==    at 0x1096C9: compare (hello.c:110)
==7662==    by 0x1093CF: shift (hello.c:55)
==7662==    by 0x109338: main (hello.c:41)
==7662==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==7662==
==7662==
==7662== Process terminating with default action of signal 11 (SIGSEGV)
==7662==  Access not within mapped region at address 0x0
==7662==    at 0x1096C9: compare (hello.c:110)
==7662==    by 0x1093CF: shift (hello.c:55)
==7662==    by 0x109338: main (hello.c:41)

110就是这条线

msgRes[j] = alphabet[(get_letter(msgEnc[j], alphabet) + i) % 52];

你失败了,因为你用 msgres == null 调用了 shift

msgEnc = msg = msgRes = mainMsg = NULL; <<<<==========
msgEncLen = msgLen = 0;

msgEnc = read_Input_Msg(&msgEncLen);
if (msgEnc)
    msg = read_Input_Msg(&msgLen);

if (msgEnc == NULL || msg == NULL)
    ret = ERROR_INPUT;
else if (msgEncLen != msgLen)
    ret = ERROR_LEN;

if (ret == NO_ERROR)
    shift(msgEnc, msg, msgRes, mainMsg, alphabet, msgEncLen);  <<<<======