gpt4 book ai didi

c - 在 C 中确定正确的预定义数组大小?

转载 作者:行者123 更新时间:2023-12-02 07:18:04 24 4
gpt4 key购买 nike

在下面的代码中,我将数组大小设置为 20。在 Valgrind 中,代码测试干净。但是一旦我将大小更改为 30,就会出现错误(如下所示)。让我感到困惑的部分是我可以将值更改为 40 并且错误消失了。改成50,又报错。然后 60 次测试干净等等。一直这样下去。所以我希望有人能够向我解释这一点。因为尽管我尽了最大的努力去思考它,但我还是不太清楚。这些错误很难查明,因为所有外观的代码都是有效的。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct record {
int number;
char text[30];
};

int main(int argc, char *argv[])
{
FILE *file = fopen("testfile.bin", "w+");
if (ferror(file)) {
printf("%d: Failed to open file.", ferror(file));
}

struct record rec = { 69, "Some testing" };

fwrite(&rec, sizeof(struct record), 1, file);
if (ferror(file)) {
fprintf(stdout,"Error writing file.");
}

fflush(file);
fclose(file);
}

Valgrind 错误:

valgrind --leak-check=full --show-leak-kinds=all\
--track-origins=yes ./fileio
==6675== Memcheck, a memory error detector
==6675== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6675== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==6675== Command: ./fileio
==6675==
==6675== Syscall param write(buf) points to uninitialised byte(s)
==6675== at 0x496A818: write (in /usr/lib/libc-2.28.so)
==6675== by 0x48FA85C: _IO_file_write@@GLIBC_2.2.5 (in /usr/lib/libc-2.28.so)
==6675== by 0x48F9BBE: new_do_write (in /usr/lib/libc-2.28.so)
==6675== by 0x48FB9D8: _IO_do_write@@GLIBC_2.2.5 (in /usr/lib/libc-2.28.so)
==6675== by 0x48F9A67: _IO_file_sync@@GLIBC_2.2.5 (in /usr/lib/libc-2.28.so)
==6675== by 0x48EEDB0: fflush (in /usr/lib/libc-2.28.so)
==6675== by 0x109288: main (fileio.c:24)
==6675== Address 0x4a452d2 is 34 bytes inside a block of size 4,096 alloc'd
==6675== at 0x483777F: malloc (vg_replace_malloc.c:299)
==6675== by 0x48EE790: _IO_file_doallocate (in /usr/lib/libc-2.28.so)
==6675== by 0x48FCBBF: _IO_doallocbuf (in /usr/lib/libc-2.28.so)
==6675== by 0x48FBE47: _IO_file_overflow@@GLIBC_2.2.5 (in /usr/lib/libc-2.28.so)
==6675== by 0x48FAF36: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib/libc-2.28.so)
==6675== by 0x48EFBFB: fwrite (in /usr/lib/libc-2.28.so)
==6675== by 0x10924C: main (fileio.c:19)
==6675== Uninitialised value was created by a stack allocation
==6675== at 0x109199: main (fileio.c:11)
==6675==
==6675==
==6675== HEAP SUMMARY:
==6675== in use at exit: 0 bytes in 0 blocks
==6675== total heap usage: 2 allocs, 2 frees, 4,648 bytes allocated
==6675==
==6675== All heap blocks were freed -- no leaks are possible
==6675==
==6675== For counts of detected and suppressed errors, rerun with: -v
==6675== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

最佳答案

问题是结构中存在填充,使 int a 在内存中始终按 4 对齐,即使在 struct record< 的数组中也是如此s。现在,20+4 可以被 4 整除,40+4 和 60+4 也是如此。但是 30+4 和 50+4 不是。因此需要添加 2 个填充字节以使 sizeof (struct record) 可以被 4 整除。

当您运行数组大小为 34 的代码时,sizeof (struct record) == 36,并且字节 35 和 36 包含不确定的值 - 即使 struct record 否则完全初始化。更糟糕的是,写入不确定值的代码可能会泄露敏感信息 - Heartbleed bug是一个典型的例子。

解决方案实际上是使用fwrite 编写结构。而是单独编写成员 - 这也提高了可移植性。也没有太大的性能差异,因为 fwrite 缓冲 写入,fread 也是如此。


附言通往 hell 的道路是由打包的 struct 铺成的,您希望像避免泛型代码中的瘟疫一样避免它们。


附言ferror(file) 几乎肯定不会在 fopen 之后为真 - 在正常故障中 fopen 将返回 NULL并且 ferror(NULL) 可能会导致崩溃。

关于c - 在 C 中确定正确的预定义数组大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55445869/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com