在C中初始化16mb数组
我对“C”比较陌生,希望能对这个话题有所了解 基本上,我正在尝试创建一个16 MB的数组,并检查内存内容是否初始化为零或“\0”或某个学校项目的垃圾值 大概是这样的:在C中初始化16mb数组,c,arrays,segmentation-fault,malloc,heap,C,Arrays,Segmentation Fault,Malloc,Heap,我对“C”比较陌生,希望能对这个话题有所了解 基本上,我正在尝试创建一个16 MB的数组,并检查内存内容是否初始化为零或“\0”或某个学校项目的垃圾值 大概是这样的: char缓冲区[16*1024*1024] 我知道程序堆栈的大小是有限制的,显然我遇到了分段错误。是否可以使用malloc()以某种方式完成此操作?当然: int memSize = 16*1024*1024; char* buffer = malloc( memSize ); if ( buffer != 0 ) { /
char缓冲区[16*1024*1024]代码>
我知道程序堆栈的大小是有限制的,显然我遇到了分段错误。是否可以使用malloc()以某种方式完成此操作?当然:
int memSize = 16*1024*1024;
char* buffer = malloc( memSize );
if ( buffer != 0 )
{
// check contents
for ( i = 0; i < memSize; i++ )
{
if ( buffer[i] != 0 )
{
// holler
break;
}
}
free( buffer );
}
int memSize=16*1024*1024;
char*buffer=malloc(memSize);
如果(缓冲区!=0)
{
//检查内容
对于(i=0;i
您可以使用malloc初始化内存,如下所示:
#define MEM_SIZE_16MB ( 16 * 1024 * 1024 )
char *buffer = malloc(MEM_SIZE_16MB * sizeof(char) );
if (buffer == NULL ) {
// unable to allocate memory. stop here or undefined behavior happens
}
然后,您可以检查内存中的值,以便(注意,这将打印很长时间):
是的,您可能需要使用malloc()
执行此操作,原因如下:
当任何程序(进程…线程…)启动时,都会给它一块内存,用于存储(除其他外…“本地”变量)。这个区域被称为“堆栈”,它肯定不会大到足以存储16兆字节
但是,任何程序都可以使用另一个内存区域:它的“堆”。这个区域(顾名思义,“堆”)没有固有的结构:它只是一个存储池,通常足够大,可以存储很多兆字节。您只需malloc()
所需的字节数,并在完成后free()
这些字节
只需定义一个与需要存储的结构相对应的type
,然后malloc(sizeof(type))
。存储将来自堆。(基本上,这就是堆的用途……)
顺便提一下,有一个名为calloc()
的库函数,它将保留一个“已知零”的区域。此外,它可能会使用巧妙的操作系统技巧来非常有效地执行此操作。严格地说,代码无法检查缓冲区是否未归零,而不会导致未定义的行为。如果类型是无符号字符
,则没有问题。但是可能有符号的char
,可能有一个陷阱值。尝试使用该值将导致UB
char buffer[16*1024*1024];
// Potential UB
if (buffer[0]) ...
最好使用不能有陷阱值的无符号字符
#define N (16LU*1204*1204)
unsigned char *buffer = malloc(N);
if (buffer) {
for (size_t i = 0; i<N; i++) {
if (buffer[i]) Note_NonZeroValue();
}
}
// Clean-up when done.
free(buffer);
buffer = 0;
定义N(16LU*1204*1204)
无符号字符*buffer=malloc(N);
if(缓冲区){
对于(size_t i=0;如果用户是C的“新手”,您可能应该包括一个free示例。您的代码会检查缓冲区是否已归零,而不存在UB风险,因此需要编辑第一句话。此外,C11表示可以通过字符类型读取陷阱表示,因此我认为char*
版本是正确的OK@MattMcNabb扫描C11并且没有清楚地看到一个char
trap的位置。任何细节都很好。@Matt McNabb,可能会有用。短期内。以后需要深入研究C11。C99+TC2(N1124)和C11都清楚地表示在6.2.6.1/5中,如果对象的存储值具有这样的表示形式,并且由没有字符类型的左值表达式读取,则该行为是未定义的。“因此,char
是否有陷阱表示并不重要;即使有,读取它们也不会导致UB。尽管我想你可能会争辩说,它也没有说明当char
的陷阱表示被读取时会发生什么,任何未定义的内容都是未定义的。C11在子句中添加“有符号字符
不得有任何填充位"。它仍然可以有陷阱表示负零,所以我用6.2.6.1/5来说明读取负零本身不会导致UB;但是我们参考6.2.6.2中关于负零的规则,看看随后对值执行的操作是否会触发UB。我们必须显式释放这个分配的内存吗?我想t当程序执行完毕后,内存会自动释放回操作系统。如果我错了,请纠正我。是的,在这种情况下,但通常这样做是很好的做法。对于任何非琐碎的代码,程序通常会运行一段时间,因此:1 malloc=1 free。因为OP对C来说显然是新的,最好立即开始正确的轨道<代码>printf(“\nAddr:0x%08x:”,(无符号int)(&buffer[i]))
警告:从指针强制转换为不同大小的整数。使用%p更方便吗?@Absolut\u Red:是的,这是一个更好的方法。我将进行编辑以反映这一点。“0x”前缀也会加倍。如果可以忽略这一点,请注意:今天许多系统使用32位int
,因此16*1024*1024
不是问题。注意一些问题16位int
仍然存在且16*1024*1024
溢出的CPU(如某些嵌入式设备)。代码可以使用16L*1024*1024
(添加了L)当然,在16位int
设备上不太可能使用16 MB数组。@chux:你能详细说明一下“L”代表什么吗?它的一般用途吗?那太好了。L
使一个常量至少typelong
long
整数的范围至少在-2000000到+2000,0之间00000范围。(-power(2,31)+1…power(2,31)-1)。
char buffer[16*1024*1024];
// Potential UB
if (buffer[0]) ...
#define N (16LU*1204*1204)
unsigned char *buffer = malloc(N);
if (buffer) {
for (size_t i = 0; i<N; i++) {
if (buffer[i]) Note_NonZeroValue();
}
}
// Clean-up when done.
free(buffer);
buffer = 0;