将文件读入字符数组的C++代码

4

我正在使用以下代码将文件读入字符数组。现在,对于小文件(比如2 MB),它可以正常执行,但是对于大文件(140 MB),在我的18 GB UBUNTU服务器上,它会出现分段错误。有人能帮助我解决这个问题吗?我认为18 GB足以将240 MB的文件存储到内存中。我正在使用64位UBUNTU并使用g ++编译。

ifstream is;

char chararray [fileSize] ;

is.read(chararray, fileSize) ;

@milleniumbug:我认为fileSize应该是一个值为240*1024*1024size_t类型... - Mr.C64
@hmjd:好吧,他说它不会。 - Lightness Races in Orbit
2
请将您的第二行代码替换为char* chararray = new char[fileSize]; - Good Night Nerd Pride
3
不需要为此介绍原始数组指针,这是一种面向C语言的解决方案。这种方法容易泄露,而且有可能会忘记使用delete[]来代替delete。相比之下,向量更好...而且从C++11开始,甚至可以在不付出复制开销的情况下从函数中返回大型向量,这要归功于返回值优化期间发生的复制省略。 - HostileFork says dont trust SE
3
不要忘记异常安全性!作为具有析构函数的类,向量可以进行自我清理。而原始指针只会泄漏!:-/ - HostileFork says dont trust SE
显示剩余3条评论
3个回答

5
如果数组是一个局部变量,它将无法适应堆栈,导致堆栈溢出。相反地,在堆上分配"数组",可以直接使用new或者间接使用std::vector
或者使用内存映射,参见mmap函数。

在命令行中运行ulimit是一种不太优雅的非可移植解决问题的方式,而在代码本身中同样可以轻松地管理这个问题。 - Richard
2
@Richard,就像我说的,使用std::vector可能更好。但是了解ulimit也没有错。 - James Kanze
@HostileFork 这取决于你想要什么。如果想要封装数据,可以。如果想要通过在末尾添加/删除来修改它,可以。如果计划将其合并到另一个将使用STL容器的代码中,那就很棒了。如果只是想获取数据并随机查看它们,则mmap()是最好的选择。这不仅涉及内存开销,还涉及执行时间。从我的观点来看,如果只需要读取数据,这更加优雅。 - peterph
3
@peterph 是的,内存映射是个好东西……不过如果你正在使用C++编程,那么使用一个被封装在类中且是平台无关的方法(https://dev59.com/iGsy5IYBdhLWcg3w8Shc)要比使用POSIX mmap更可取。只是如果一个问题标记为C++,我认为需要反对那些建议调用new[] *(当然还有malloc……)*的方法。 - HostileFork says dont trust SE
1
如果你在使用C++编程,你会用一个类来封装mmap函数,并在析构函数中使用munmap函数。并且可能会给这个类一个接口,使其尽可能接近std::vectorstd::array的接口,以便用户感到熟悉。但由于涉及到的工作量,我建议只需读入std::vector,直到需要性能时再使用该类(但如果我需要它一次,我会将该类放入我的工具包中,并立即使用它)。 - James Kanze
显示剩余3条评论

2

不要在栈上分配char数组,建议使用std::vector,它会在上进行动态分配:

std::vector<char> buffer(fileSize);
is.read(&buffer[0], fileSize);

1
GCC编译器有一个默认命令叫做size!使用GCC编译器编译程序。然后你就可以得到文件大小了!
gcc -Wall test.c
size

这是一个普通的C程序!由于您没有指定任何参数,它会将./a.out作为默认参数!

如果您需要应用一些优化,代码将变得如下所示...

praveenvinny@ubuntu:~/Project/New$> gcc -Wall -o1 -fauto-inc-dec test.c -o Output
praveenvinny@ubuntu:~/Project/New$> size output
text       data     bss     dec     hex filename
1067       256      8       1331    533 output

请使用文本部分来计算代码大小。 如果您想考虑全局数据大小,可以使用数据和bss。
这将打印出代码大小。
time -f "%e" -o Output.log ./a.out

将执行时间打印到名为Output.log的日志文件中


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接