我的代码在 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;
}
第一个错误:
您正在为 index
和 input[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
转换格式说明符,假设您启用了所有编译器警告。您可能想阅读此内容:
我是编码新手。作为一道练习题,我编写了一个程序来按字母顺序对字符串进行排序,就像在字典中一样。我的程序将输入: (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;
}
第一个错误:
您正在为 index
和 input[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
转换格式说明符,假设您启用了所有编译器警告。您可能想阅读此内容: