我有一个基本的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。
随机方法和阅读文件之间的关系是什么,以及我为什么会出现这种行为?
更新:我已malloc
从sizeof(wchar_t) * 100
修复sizeof(wchar_t) * 50
。它没有改变任何东西。我的行最多约15个字符,并且有少于2000行(保证)。
更新2:
-Wall
编译,没有问题。-Werror
编译,没有问题。valgrind
也没发现任何泄漏。 gdb
调试,它只是没有进入while循环(fgetws
调用返回0)。 更新3:我在Linux上遇到浮点异常,因为numNameLines
为零。
更新4 :我验证我对MaleNames.txt
具有读取权限。
更新5:我发现重音的非英文字符(例如Â
)在阅读线条时会出现问题。 fgetws
停止了他们。我尝试过设置区域设置(分别为setlocale(LC_ALL, "en.UTF-8");
和setlocale(LC_ALL, "tr.UTF-8");
),但没有成功。
答案 0 :(得分:3)
fgetws()
正在尝试读取多达100个宽字符。循环中的malloc()
调用分配50个宽字符。
wcscpy()
调用会复制读取的所有宽字符。如果已读取超过50个宽字符(包括终止nul),则wcscpy()
将超出分配的缓冲区。这导致了不确定的行为。
而不是在循环中乘以50,乘以100.或者,更好的是,计算字符串读取的长度并使用它。
除上述内容外,如果文件包含超过2000行,您的代码也会溢出缓冲区。你的循环需要检查它。
代码中的许多函数都可能失败,并会返回一个值来表示。您的代码没有检查任何此类故障。
在OS X下运行的代码是偶然的。行为未定义,这意味着当使用任何编译器构建时,任何主机系统都可能出现故障。似乎在一个系统上正确运行,而在另一个系统上失败,实际上是对未定义行为的有效响应集。
答案 1 :(得分:0)
找到解决方案。从一开始就是关于语言环境的。经过实验和数小时的研究,我偶然发现了这一点:http://cboard.cprogramming.com/c-programming/142780-arrays-accented-characters.html#post1066035
#include&lt; locale.h&gt;
setlocale(LC_ALL,&#34;&#34;);
将语言环境设置为空字符串可以立即解决我的问题。