我正在使用Visual Studio 2010。
我有一个三维结构数组,我认为,它给了我错误的错误。 该数组是从
定义的#define BUCKETS 2048
#define B_ENTRIES 4096
typedef struct fpinfo
{
unsigned long long offset;
unsigned long length;
char fing_print[33];
}fpinfo;
作为
struct fpinfo search_buf[TNK_CACHE_SIZE][BUCKETS][B_ENTRIES];
问题是,
当我将 TNK_CACHE_SIZE 定义为6时,它不会给我编译时错误,但在我尝试写入时会在运行时出现访问冲突错误。
另一方面,如果我将 TNK_CACHE_SIZE 定义为3,它确实给出了以下编译时错误。
1> LINK:致命错误LNK1248:图像尺寸(86CB7000)超出最大值 允许的大小(80000000)
1)为什么它在编译时忽略第一个声明,而第二个声明不是第二个声明,而它只是第一个声明的一半。
2)堆栈上声明的最大允许大小是多少?
3)这个允许的大小是否包括项目中的所有其他内存分配,还是一个接一个的内存分配,直到 没有可分配的内存空间 和最后一个不能被分配标记?
答案 0 :(得分:2)
编译器和链接器对图像大小的检查可能不完美。如果你把它做得太大,可能会有一些计算结果导致不正确的结果,这似乎是在有效的图像大小范围内。即您的工具链会在图像大小过大时捕获一个小错误,但不会出现大错误。
请注意,如果您将数字86CB,7000
加倍,则会得到一个需要超过32位的数字,即1,0D96,E000
。如果计算以32位完成,则可能会将其切割为D96,E000
,从而使图像大小在范围内,但完全错误。
尝试使用malloc
动态分配空间。
答案 1 :(得分:2)
在堆栈上分配这样的大对象并不是一个好主意,但是你可以通过两种方式覆盖MSVC的默认堆栈大小:
使用/F
选项(在项目属性中进入 C / C ++ 部分,然后命令行并在附加选项字段中写入/ F: bytes 。无论如何,这不是一个好主意,因为它仅适用于一步编译和链接。
在项目属性中,转到链接器部分,然后系统,并在堆栈中写下您需要的尺寸预留大小字段。
答案 2 :(得分:1)
简单的事实是不应该在堆栈上声明此数组。
Windows中的tyical堆栈大小为每个线程2Mb。请注意,每个线程,所以即使你可以使堆栈变大,你的系统也会陷入困境。我甚至不确定堆栈数据是否支持虚拟内存磁盘交换,但如果确实如此,您的代码运行速度会非常慢。
静态或动态分配会更合适,但即便如此,对于大多数系统来说,这也是一个沉重的负载,尤其是32位系统。使用内存映射文件可能更有效。这与磁盘交换的工作方式相同,但是您明确地请求它,而不是让操作系统内存管理器以非确定的方式做出决定。
答案 3 :(得分:0)
3 * 2048 * 4096 * sizeof(pinfo)远远超过千兆字节。这只是为了你的桌子,所以是的,你的形象将是巨大的,并且显然比VS默认允许的大。
最好动态分配内存。
/**
* Allocate memory in a single contiguous block. Be sure to free it
* when you don't need it anymore.
*/
fpinfo *search_buf_store = malloc(sizeof *search_buf_store *
TNK_CACHE_SIZE *
BUCKETS *
B_ENTRIES);
/**
* Declare search_buf as a pointer to a 2-d array, and set it to point
* to the block we just allocated. You can then index search_buf
* as you would a regular 3-D array. Just be sure that if you pass search_buf
* to any functions, you declare it in the parameter list just like it's
* declared here.
*/
fpinfo (*search_buf)[BUCKETS][B_ENTRIES] =
(fpinfo (*)[BUCKETS][B_ENTRIES]) search_buf_store;