Valgrind对结构+工会的行为

时间:2015-11-18 20:03:32

标签: c valgrind

我有一个很大的C项目,感谢valgrind,我清理了一些内存管理方面的混乱。除了一件事,我清理了一切,经过一周的分析后,我开始认为这是对我的代码的误解,而不是我的错误。该程序运行良好,但这没有任何意义(我已经看到了程序运行好几周然后因为在int中第31次翻转而卡住的情况)。

我的代码使用了下一个想法:存储(就我的项目而言,"仓库"),它包含我想要构建的所有类型的结构。我使用Xlib中的技巧在内存中保持尽可能小:

 typedef struct
 {
     // data
 } TypeA

 typedef struct
 {
     // data
 } TypeB

 typedef struct
 {
     // data
 } TypeC

 typedef union
 {
    TypeA typea;
    TypeB typeb;
    TypeC typec;
 } UniType;

 typedef struct
 {
     int type;
     UniType data;
 } Element;

然后我创建一个元素:

SmlErrors SmlWhsAdd(SmlElement element, SmlIndex * index)
{
    SML_CHECKPTR(index);

    SmlElement * ptrold = warehouse.elem;

    warehouse.elem      = realloc(warehouse.elem,
                                  (++warehouse.elemcount) * sizeof(SmlElement));
    if (!(warehouse.elem))
    {
        warehouse.elem = ptrold;
        *index         = 0;
        warehouse.elemcount--;
        return SML_ERR_BADALLOC;
    }

    warehouse.elem[warehouse.elemcount - 1] = element;

    *index = (warehouse.elemcount - 1);

    return SML_ERR_SUCCESS;
}

对于那些认为ptr = realloc的人(ptr ...很糟糕 - 看得更近,我保存旧的并恢复它。我计划用myalloc替换所有的alloc工具将程序崩溃而不是继续工作

这段代码很清楚,valgrind是沉默的。除一例外。我的一个" TypeX"结构(如果确切地说,类型为child-of-TypeX)包含一个数组:

SmlIndex     sprite[SML_THEMEBLOCK_SIZE];

每个精灵也是来自仓库的索引,因此它是移动设备中的移动设备,因为该数组是该仓库元素之一(在杰克建造的房屋中)。

我使用前面提到的函数在其中一个sprite中写入值:

SML_CHECKLOC(SmlImageCreate(&(widget->sprite[i]),
                            widget->geometry.size));
// Which calls `WhsAdd` with `&(widget->sprite[i]` as `index`-parameter.

每当我这样称呼它时,valgrind就会抱怨Invalid write of size 4。每次我尝试使用sprite[x]之后的值 - Invalid read of size 4。如果确切的话,它会抱怨以下这一行:

*index = (warehouse.elemcount - 1);

我的系统是32位,SmlIndex是uint32_t

请给我一个关于挖掘地点的线索。经过一周的研究,我没有想法。这就是为什么我开始认为这可能是valgrind的错误 - 我也听说它在工会和结构中工作很奇怪。

还有一件事。

widget->sprite[i] = 0; // No complainings.
SmlImageCreate(&(widget->sprite[i], ...) // Complainings.

有人可以帮我一把吗?我在沼泽地里淹死了。关于在哪里寻找的任何建议。任何东西。

UPD : MCVE:http://pastebin.com/r5T5ZBPC

此致 亚历克斯。

1 个答案:

答案 0 :(得分:1)

(编辑历史记录:MCVE最初使用未初始化的变量,但在初始化所有这些变量后,问题仍然存在)

在MCVE中,问题来自:

SmlWhsAdd(sprite, &(warehouse.elem[window].data.wdg.sprite[0]));

第二个参数是指向先前调用realloc所分配的空间的指针。

但是,在SmlWhsAdd函数内,在此空间上调用realloc,它会分配一个新块并释放旧块。这使得第二个参数指向释放的空间。

要解决此问题,我的建议是审核SmlWhsAdd的所有用法,并避免传递warehouse.elem下的指针。

一个选项可能是使用临时变量,然后在调用后分配索引;另一种选择可能是传递一些其他信息,允许SmlWhsAdd函数在执行realloc之后计算写入索引的位置;或者如果索引总是在最后,你甚至根本不需要那个参数,因为调用者可以在warehouse.elemcount-1后执行。{/ p>