【问题标题】:simple 4-line C program with massive malloc only segfaults with Valgrind带有大量 malloc 的简单 4 行 C 程序,仅带有 Valgrind 的段错误
【发布时间】:2014-08-23 02:55:58
【问题描述】:

在没有 valgrind 的情况下运行以下内容时,我没有收到段错误。当它与 valgrind 一起运行时,我会这样做。这似乎是 malloc 大小的结果,因为如果我把它变成那个大小的 1/4,它就不会发生。

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

int main()
{
    float *a = malloc(400000000 * sizeof(float));
    a[5] = 3.0;
    printf("%f\n", a[5]);
    free(a);
}

这是 valgrind 的输出

==31972== Memcheck, a memory error detector
==31972== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==31972== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==31972== Command: ./seg
==31972== 
==31972== Invalid write of size 4
==31972==    at 0x80484A5: main (seg.c:8)
==31972==  Address 0x5f5e0ffc is not stack'd, malloc'd or (recently) free'd
==31972== 
==31972== 
==31972== Process terminating with default action of signal 11 (SIGSEGV)
==31972==  Access not within mapped region at address 0x5F5E0FFC
==31972==    at 0x80484A5: main (seg.c:8)
==31972==  If you believe this happened as a result of a stack
==31972==  overflow in your program's main thread (unlikely but
==31972==  possible), you can try to increase the size of the
==31972==  main thread stack using the --main-stacksize= flag.
==31972==  The main thread stack size used in this run was 8388608.
==31972== 
==31972== HEAP SUMMARY:
==31972==     in use at exit: 0 bytes in 0 blocks
==31972==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==31972== 
==31972== All heap blocks were freed -- no leaks are possible
==31972== 
==31972== For counts of detected and suppressed errors, rerun with: -v
==31972== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault

如果我做对了,那大约是 1.5 GB 的内存。

如果我在 运行 bash 命令 free -m 时执行它,看起来我有大约 2 GB 的可用内存。或许这已经接近尾声了?

有什么想法吗?如果我分配更多的内存,这是否意味着我'接近' 没有 valgrind 的段错误?

【问题讨论】:

  • 我会说你的数组大小有问题。 Valgrind 为其结构使用额外的内存,因此其结构的大小加上您的数组超出了 valgrind 的处理能力。
  • 另外,我的机器上的代码和 valgrind 没有任何问题
  • @MichałWalenciak +1 运行它。您能否通过增加要 malloc 的内存来复制 valgrind 错误消息?
  • @bytefire:我可以将内存使用量增加到 800000000 个浮点数,它仍然可以。当我增加到 810000000 时,由于访问 0x14(malloc 必须返回 nullptr)而出现段错误。段错误发生在两种情况下:正常运行和 valgrind 运行。我无法重现 valgrind/non-valgrind 运行之间的差异

标签: c segmentation-fault malloc valgrind


【解决方案1】:

malloc() 尝试分配一个 连续 内存块。您的系统中总共可能有 2GB 空闲空间,但很可能它不存在于单个块中。这就是问题所在。我敢打赌,如果你真的检查过,你会发现内存分配失败了。

在这种情况下,您正在尝试访问第 2 行上的 NULL 指针。

根据documentationmalloc

默认情况下,Linux 遵循乐观的内存分配策略。 这意味着当 malloc() 返回非 NULL 时,不能保证 内存真的可用。万一事实证明 系统内存不足,一个或多个进程将被 OOM杀手。有关详细信息,请参阅 proc(5) 中的 /proc/sys/vm/overcommit_memory 和 /proc/sys/vm/oom_adj, 和 Linux 内核源文件 文档/vm/overcommit-accounting。

所以我想那里还有一个额外的不可预测因素。

【讨论】:

  • 我也想过,但在这里会给出不同的信息:Address 0x5f5e0ffc is not stack'd, malloc'd or (recently) free'd
  • 我写的一个实际程序遇到了这个问题,当没有 Valgrind 运行时,它不仅没有段错误,而且也有效(并且程序需要对每个浮点数进行读/写操作在那个街区)。
  • @user3391564:我在您的代码中看不到任何问题(可能除了在 malloc 之后缺少 if 声明 a == 0 ;))
  • @MichałWalenciak 很奇怪,但 Valdgrind 文档指出:请注意,Memcheck 只告诉您您的程序即将访问非法地址的内存。它不能阻止访问的发生。因此,如果您的程序进行通常会导致分段错误的访问,您的程序仍将遭受同样的命运。
  • @dandan78:您可能会访问无效(或者更确切地说是未分配)内存而不会崩溃。通常访问未分配的页面会导致段错误,但您可能很幸运能够访问已分配页面上的未分配内存;)它不应该对您的程序造成段错误,但可能会破坏堆信息或覆盖您使用的其他变量的区域。
猜你喜欢
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多