尝试创建100MB的缓冲区时出现分段错误
Segmentation fault when trying to create a buffer of 100MB
我正试图将一个大型二进制文件写入C++程序的缓冲区。GDB总是在尝试创建与读取的文件大小相同的缓冲区后得到一个segfault。它要么在fclose(pf)、reback或f(open)上失败,这让我在尝试创建缓冲区时相信有什么问题。我的代码段如下。
static int fileTransfer(struct mg_connection *conn, char * filename){
FILE *fp = fopen(filename, "r");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
char buf[size];
fclose(fp);
// This is an attempt to stop a segment fault from rewind.
fp = fopen(filename, "r");
conn->connection_param = (void *) fp;
size_t n = 0;
if(fp != NULL)
{
n = fread(buf, 1, sizeof(buf), fp);
mg_send_data(conn, buf, n);
if(n < sizeof(buf) || conn->wsbits != 0)
{
fclose(fp);
conn->connection_param = NULL;
}
}
return 1;
}
我曾尝试在这段代码中放入print语句,但它们不会打印到控制台,因为它们在单独的线程中运行。有人能给我一些关于为什么会发生这种segfault的见解,或者关于如何提高代码效率的建议吗。
我应该注意,这段代码可以在1和10MB的文件上正常工作,但不能在更大的文件上工作。
永远不要这样做:
int size = ftell(fp);
char buf[size];
您是在STACK上创建大小,而不是在堆上。。。。堆栈上的100MB将不起作用。
而且。。。size必须是一个常量,而不是来自ftell()
的数字。我甚至不知道它是如何编译的。。。
您必须使用malloc()
或new
运算符来分配内存。
static int fileTransfer(struct mg_connection *conn, char * filename){
FILE *fp = fopen(filename, "r");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
char * buf = new char[size]; // fix also here!
fclose(fp);
// This is an attempt to stop a segment fault from rewind.
fp = fopen(filename, "r");
conn->connection_param = (void *) fp;
size_t n = 0;
if(fp != NULL)
{
n = fread(buf, 1, size, fp); // fix also here!
mg_send_data(conn, buf, n);
if(n < size || conn->wsbits != 0)
{
fclose(fp);
conn->connection_param = NULL;
}
}
delete [] buf; // and you have to deallocate your buffer
return 1;
}
您正在创建一个具有自动存储持续时间的缓冲区,这意味着它将通过g++放在堆栈上。我所知道的任何操作系统的默认堆栈大小都低于100MB,这意味着它将在支持它们的系统上导致segfault。
尝试用动态存储持续时间分配缓冲区,这将把它放在堆上。
发生的事情实际上是这个网站的名字!基本上,发生的事情是你的程序被创建了——它为堆栈分配了一定数量的内存。
创建char buf[size]
时,使用的是称为可变长度数组(VLA)的C99功能。这将在堆栈上为buf
分配空间。但是,buf
对于堆栈来说太大,所以您的程序会失败。
为了解决此问题,您应该先使用char * buf;
,然后执行buf = malloc(size)
。这将把buf放在堆上,堆比堆栈大。它还允许您通过检查malloc()
是否返回NULL
来检查您是否没有足够的内存。不过,在退出之前,您需要确保free(buf)
!
附带说明一下,您可以使用ulimit -s
命令检查堆栈上有多少空间。
这似乎需要在堆栈上分配很多。如果你把它堆起来呢?
char *buf = new char[size];
使用std::vector
。这样就不会有堆栈空间的问题,也不会有编写非标准C++代码的其他问题:
#include <vector>
//...
static int fileTransfer(struct mg_connection *conn, char * filename)
{
FILE *fp = fopen(filename, "r");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
std::vector<char> buf(size);
fclose(fp);
fp = fopen(filename, "r");
conn->connection_param = (void *) fp;
size_t n = 0;
if(fp != NULL)
{
n = fread(&buf[0], 1, buf.size(), fp);
mg_send_data(conn, &buf[0], n);
if(n < buf.size() || conn->wsbits != 0)
{
fclose(fp);
conn->connection_param = NULL;
}
}
return 1;
}
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?