【问题标题】:Valgrind: Address 0x0 is not stack'd, malloc'd or (recently) free'd for larger input values onlyValgrind:地址 0x0 不被堆栈、malloc 或(最近)释放,仅用于更大的输入值
【发布时间】:2018-10-12 08:19:05
【问题描述】:

我正在尝试实现 Dijikstra,这是我拥有的图形生成代码

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <math.h>
#define MAX 300
int main (int argc, char *argv[]){
    int v = atoi(argv[1]);
    int SIZE = v*v;
    int* adjMatrix = malloc(sizeof(int)* SIZE);
    graphGeneration(adjMatrix, v);
    free(adjMatrix);
    return 0;
}

void graphGeneration(int* adj, int numV){
    int i, j, r;
    for(i = 0; i< numV; i++){
        for(j=0; j < numV; j++){
            if(i == j){
                adj[i * numV + j] = 0;
            }
            else{
                r = rand() % MAX;
                adj[i * numV + j] = r;
                adj[j * numV + i] = r;
            }
        }
    }

}

当我尝试 1000 的 v 值时,它似乎工作正常,但是当我尝试输入 v = 10,000+ 的值时,我得到一个段错误(特别是 50,000 是我注意到的数字)。运行 valgrind 让我在此方法的标题中出现错误。 为方便起见,在此转发:

Invalid write of size 4
at 0x400800: graphGeneration 
by 0x4006E3: main
Address 0x0 is not stack'd, malloc'd or (recently) free'd
Access not within mapped region at address 0x0

有人对如何调试有任何想法,或者这里是否有任何明显的错误?

我在 valgrind 中也注意到了这一点

Warning: silly arg (-7179869184) to malloc()

我不确定它是否相关,但这似乎也是一件奇怪的事情。

【问题讨论】:

  • 首先,malloc() 采用什么类型的参数?二、遇到段错误时malloc()返回什么?
  • @AndrewHenle 抱歉,我不确定我是否理解,但我会尽力提供详细信息。我要分配的是一维格式的二维整数数组的大小。 (命令行的输入是数组的宽度)我从编译器得到的错误只是分段错误(核心转储)
  • 使用任何体面的现代编译器,您应该能够执行sizeof(double[v][v]),因此您不必手动进行计算。然后,检查malloc 的返回是否有如此大的分配。第三,用小例子尝试你的代码,这样你就有机会调试。

标签: c memory malloc valgrind


【解决方案1】:

看看一些malloc() manual:它的参数是size_t类型是有原因的。 int 不能保证容纳任何可能的对象大小,size_t 是。顺便说一句,它是无符号的——负大小没有多大意义。

那就写吧

size_t SIZE = ((size_t)v) * v;

由于您的vint,因此您必须通过转换其中一个参数来强制此乘法作为size_t 完成。

更好的方法是将v 设为unsigned long 并使用strtoul() 而不是atoi()


然后,在使用之前检查您的malloc() 的结果。即使使用正确的大小参数,它仍可能返回NULL。如果是这样,这仅表示您当时没有足够的可用 RAM

毕竟,使用 v=10000 并假设 int 占用四个字节(这很常见),您已经尝试一次分配 400 MB。

【讨论】:

  • 嗯,所以可能它溢出了,因此出现了愚蠢的错误?这绝对是可能的,尽管如果发生这种情况,我会有点不高兴,因为我使用的 HPC 的 RAM 应该比 400MB 多得多。也许,虽然,我只是没有分配空间,但将该行更改为 size_t 似乎对我没有任何改变。
  • 不仅SIZE 应该是size_t,而且v,所以v*v 结果已经是size_t。否则,如果v&gt;=50000,则乘法将溢出。
  • @mch 好一个,我在源头上看的不够近!将编辑此答案。
  • 为了检查 malloc,我只需要一个条件语句来查看我 malloc 的内容是否为空?
  • 对。任何malloc()没有检查返回值都是一个错误。常用成语:x = malloc(sizeof *x); if (!x) { fputs("out of memory!", stderr); exit(EXIT_FAILURE); }.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
  • 2020-04-07
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多