我有一个基本的C程序,它从工作目录中包含数百行的文本文件中读取一些行,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
srand((unsigned)time(0));
char *nameFileName = "MaleNames.txt";
wchar_t line[100];
wchar_t **nameLines = malloc(sizeof(wchar_t*) * 2000);
int numNameLines = 0;
FILE *nameFile = fopen(nameFileName, "r");
while (fgetws(line, 100, nameFile) != NULL) {
nameLines[numNameLines] = malloc(sizeof(wchar_t) * 100);
wcsncpy(nameLines[numNameLines], line, 100);
numNameLines++;
}
fclose(nameFile);
wchar_t *name = nameLines[rand() % numNameLines];
name[wcslen(name) - 1] = '\0';
wprintf(L"%ls", name);
int i;
for (i = 0; i < numNameLines; i++) {
free(nameLines[i]);
}
free(nameLines);
return 0;
}
它基本上是逐行读取我的文本文件(定义为宏,存在于工作目录中),其余部分无关紧要,它在我的Mac(使用llvm/Xcode)上运行得很完美,正如预期的那样,当我试图编译(同样,没有什么花哨的gcc main.c
)并在Linux服务器上运行它时,它要么:
- 存在错误代码2(表示未读取任何行)。
- 只读取前3行从我的文件与数百行。
是什么导致了这种不确定性(和不正确的)行为?我试着注解掉第一行(随机种子)并再次编译,它 * 总是 * 以返回代码2退出。
随机方法和读取文件之间的关系是什么,为什么我会得到这种行为?
- 更新:**我把
malloc
从sizeof(wchar_t) * 50
修改为sizeof(wchar_t) * 100
,没有任何变化,我的行最多15个字符左右,远远少于2000行(保证)。
- 更新:**我把
- 更新2:**
- 我用
-Wall
编译过,没有问题。 - 我用
-Werror
编译过,没有问题。 - 我已经运行了
valgrind
,也没有发现任何泄漏。 - 我用
gdb
调试过,它只是没有进入while循环(fgetws
调用返回0)。 - 更新3:**我在Linux上遇到浮点异常,因为
numNameLines
为零。
- 更新3:**我在Linux上遇到浮点异常,因为
- 更新4:**我验证了我是否具有对
MaleNames.txt
的读取权限。
- 更新4:**我验证了我是否具有对
- 更新5:**我发现重读的非英语字符(例如
Â
)在读取行时会导致问题。fgetws
会在这些字符上暂停。我尝试设置语言环境(分别设置setlocale(LC_ALL, "en.UTF-8");
和setlocale(LC_ALL, "tr.UTF-8");
),但不起作用。
- 更新5:**我发现重读的非英语字符(例如
3条答案
按热度按时间hzbexzde1#
fgetws()
正在尝试读取最多100个宽字符。循环中的malloc()
调用分配50个宽字符。wcscpy()
调用复制所有读取的宽字符。如果读取的宽字符超过50个(包括终止的nul),则wcscpy()
将溢出分配的缓冲区。这将导致未定义的行为。不要在循环中乘以50,而是乘以100。或者,更好的是,计算string read的长度并使用它。
独立于上述内容,如果文件包含超过2000行,代码也会溢出缓冲区。您的循环需要对此进行检查。
代码中的许多函数可能会失败,并将返回一个值来指示失败。代码不会检查任何此类失败。
你的代码在OS X下运行是偶然的。行为是未定义的,这意味着当用任何编译器构建时,在任何主机系统上都有可能失败。在一个系统上看起来运行正确,而在另一个系统上失败,实际上是对未定义行为的一组有效响应。
6l7fqoea2#
找到了解决办法。从一开始,一切都与地点有关。经过试验和几个小时的研究,我偶然发现了这个:www.example.comhttp://cboard.cprogramming.com/c-programming/142780-arrays-accented-characters.html#post1066035
包括< locale.h >
设置区域设置(LC_ALL,"");
将locale设置为空字符串立即解决了我的问题。
7xllpg7q3#
设置区域设置(LC_ALL,“”);也解决了我的问题