我的代码在 Linux 中顺利运行到结尾,但在 Windows 中突然结束

My code runs smoothly to the end in Linux but ends abruptly in Windows

我是编码新手。作为一道练习题,我编写了一个程序来按字母顺序对字符串进行排序,就像在字典中一样。我的程序将输入: (a) 用户心中的字符串个数 (b) 字符串,一个接一个,每个字符串都通过按回车键终止。 它将初始输入存储在大小为 MAXSTR 的缓冲区数组中,并同时计算字符数。然后它在内存位置 input[i] 创建分配所需大小的内存并将缓冲区复制到该位置。它还创建了一个索引数组,数组元素的值为 0、1、2 ...,每个元素对应于第 0 个字符串、第 1 个字符串、第 2 个字符串 ...等等。函数 dictsort 根据相应字符串的字母位置对索引数组进行排序。 我的程序在 Linux 台机器上运行流畅。然而,在 Windows 上,它编译正常,但是在 运行 可执行文件中,它在执行行 "input[i]=(char)malloc(jsizeof(char));"。如果你们中的任何人都可以指出正在发生的事情,那将会有很大的帮助。请注意,我的问题仅与主要功能有关。排序函数工作正常,因此这些函数既没有包含也没有从下面的代码中注释掉。

#define MAX 10000
#define MAXSTR 100
#include<stdio.h>
#include<stdlib.h>
//int dictsort(char **mainarray, size_t *indexarray, size_t elementcount);
//int strcompare(char* str1, char* str2);
//int getvalue(int input);

int main(void){
    size_t n, i, j,k;
    char buffer[MAXSTR];
    int c;
    size_t *index;
    char **input;
    printf("Input number of elements:\t");
    scanf("%ld", &n);
    n=n<MAX ? n : MAX;
    index=(size_t*)malloc(n*sizeof(size_t));
    getchar(); // flush the newline after scanf

    for(i=0;i<n;++i){
        index[i]=i;
        printf("Input element %ld:\t", i+1);
        j=0;
        while(((c=getchar())!=EOF) && (c!='\n') && (c!='[=12=]') && (j<MAXSTR-1)){
            buffer[j]=c;
            ++j;
        }
        buffer[j]='[=12=]';
                              printf("Upto 1\n"); //program comes upto here
        input[i]=(char*)malloc(j*sizeof(char));
                              printf("Upto 2\n"); //never reaches here
        for(k=0;k<j+1;++k){
            input[i][k]=buffer[k];
        }
        
    }

    //dictsort(input, index, n);        //disabled for debugging

    printf("The sorted array is: \n");
    for (i=0;i<n;++i){
    printf("%s  ", input[index[i]]);
    }

    for(i=0;i<n;++i){
        free(input[i]);
    }

    free(index);

    return 0;
}

第一个错误:

您正在为 indexinput[i] 分配内存,而不是为 input 本身分配内存。这意味着您正在取消引用以下行中的未初始化指针:

input[i]=(char*)malloc(j*sizeof(char));

这将调用 undefined behavior,这解释了为什么它在一个平台上在该行崩溃,但在另一个平台上工作。

第二个错误:

input[i]=(char*)malloc(j*sizeof(char));

不会分配足够的 space 来存储字符串。由于 j 是没有终止空字符的字符串的大小,因此您必须分配 j+1 字节。

由于没有为字符串分配足够数量的字节,以下循环将越界访问内存缓冲区input[i]

for(k=0;k<j+1;++k){
    input[i][k]=buffer[k];
}

这将调用未定义的行为。

第三个错误:

程序中未定义行为的另一个来源是以下行:

scanf("%ld", &n);

size_t 的正确转换格式说明符是 %zu,而不是 %ld。有关详细信息,请参阅函数 scanf 的文档。

在 64 位 Microsoft Windows 上,long 的宽度为 4 个字节,而 size_t 的宽度为 8 个字节。因此,因为您使用 long 而不是 size_t 的格式说明符,函数 scanf 可能只写入变量 n 的一半,留下另一半变量未初始化。这很可能会在您稍后在程序中读取 n 的值时造成麻烦。

大多数编译器会警告您使用错误的 scanf 转换格式说明符,假设您启用了所有编译器警告。您可能想阅读此内容: