LINUX.ORG.RU

Что не нравится valgrind? (invalid write of size 4)

 ,


0

2
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;
}

Снаружи приходят адекватные данные.



Последнее исправление: Edible (всего исправлений: 1)

Снаружи приходят адекватные данные.

Не верю (с)

anonymous
()
Ответ на: комментарий от SZT
// main
   SmlIndex win1;
   ...
   LOG(SmlWindowCreate(&win1));
   ...
// main end



SmlErrors SmlWindowCreateCore(SmlIndex * index, SmlIndex root, SmlGeometry geometry, int32_t borderwidth)
{
   ...
   SML_CHECKLOC(SmlWhsAdd(window, index));
}

SmlErrors SmlWindowCreate(SmlIndex * index)
{
   ...
   SML_CHECKLOC(SmlWindowCreateCore(
                 index, SML_ROOTWINDOW,
                 (SmlGeometry)
                 {
                     (SmlPoint){SML_DEFAULT_WINDOW_X,     SML_DEFAULT_WINDOW_Y},
                     (SmlSize) {SML_DEFAULT_WINDOW_WIDTH, SML_DEFAULT_WINDOW_HEIGHT}
                 },
                 SML_DEFAULT_WINDOW_BORDER));
                 
    ...

    SML_CHECKLOC(SmlWidgetCreate(&(warehouse.elem[*index].data.wdg), SML_THEMEBLOCK_WINDOW));
}

SmlErrors SmlWidgetCreate(SmlWidgetData * widget, SML_THEME_BLOCKS type)
{
   ... // no actions with widget->sprites
   SML_CHECKLOC(SmlWidgetSpritesCreate(widget));
   ...
}

SmlErrors SmlWidgetSpritesCreate (SmlWidgetData * widget)
{
   	int32_t i;
	
	for (i = 0; i < SML_THEMEBLOCK_SIZE; i++)
	{
        widget->sprite[i] = 0;
        if ((SML_WIDGET_POSSIBLESPRITES[i]) &&
            (widget->theme[i]))
		{
		    SML_CHECKLOC(SmlImageCreate(&(widget->sprite[i]),
		                                  widget->geometry.size));
         ...
}

SmlErrors SmlImageCreate(SmlIndex * index, SmlSize size)
{
   ... // No actions with index
   SML_CHECKLOCEX(SmlWhsAdd(image, index));
   ...
}
Edible
() автор топика
Ответ на: комментарий от beastie

Еще один, блин. Бести, ну хоть ты не тупи и в ман не тыкай, а сначала код посмотри. В случае неудачного реаллока указатель откатывается на oldptr.

Edible
() автор топика
Ответ на: комментарий от Edible

А да, сразу не приметил.

А что у нас с SmlIndex? Какой тип?

Судя по ошибке, туда пишется int32_t — то к чему приводится выражение, а что там на самом деле?

beastie ★★★★★
()
Ответ на: комментарий от beastie

Судя по ошибке, туда пишется int32_t

uint32_t

/* E */ typedef uint32_t SmlIndex;
typedef struct
{
    SmlBool        halt;
    SmlAtoms       atoms;
    SmlEngine      engine;
    SmlScreen      screen;
    SmlElement   * elem;
    uint32_t       elemcount;
    SmlDirectories directories;
} Warehouse;
Edible
() автор топика
Ответ на: комментарий от Edible

Я твоему прошлому я говорил, и этому скажу — кривой у тебя код. Внимание, которое читатель потратит на выяснение того, что с realloc бага нет, он не потратит на выявление реальных багов.

i-rinat ★★★★★
()
Ответ на: комментарий от beastie

SmlWhsAdd >

warehouse.elem      = realloc(warehouse.elem,
                                  (++warehouse.elemcount) * sizeof(SmlElement));
typedef struct
{
	SmlGeometry  geometry;
	SmlIndex     sprite[SML_THEMEBLOCK_SIZE];
	SmlIndex     theme [SML_THEMEBLOCK_SIZE];
	int32_t      state;
	SmlBool      visible;
	char *       caption;
    SmlBool      enabled;
	SmlWidgetExt ext;
} SmlWidgetData;

typedef union
{
    SmlGenericData  gen;
    SmlWidgetData   wdg;
    SmlTimerData    tmr;
    SmlImageData    img;
    SmlFontData     fnt;
    SmlThemeData    thm;
    SmlGradientData grd;
    SmlMemoryData   mem;
} SmlElemData;

typedef struct
{
    SmlElemType    type;
    SmlElemSubtype subtype;
    SmlBool        exists;
    SmlIndex       parent;
    SmlElemData    data;
} SmlElement;

Edible
() автор топика
Ответ на: комментарий от Edible

Не понятно ничего из этого кода. Есть полные исходники? Я бы например добавил следилку, чтобы на каждый malloc realloc free на который имеет право(может) указывать этот твой SmlIndex * index создавался(malloc/alloca) или модифицировался(realloc) или удалялся(free) элемент из специального связного списка, вот примерно вот такого

struct l_l_memreg
{
    struct l_l_memreg *next;
    struct l_l_memreg *prev;
    void *fr_addr;
    void *to_addr;
};
И чтобы вот эту строчку
*index = (warehouse.elemcount - 1); 
переписать как
if (checkifallowed(index) == FAIL ) {error();}
*index = (warehouse.elemcount - 1);
который пробежится по всем элементам этого связного списка и проверит, попадает ли этот index в аллоцированную память, которую разрешено под этот index. В качестве функции error можно например распечатать бектрейс, т.е. ту последовательность функций и аргументы переданные в них, которая привела к тому что эта штука пишет в запрещенное место. http://man7.org/linux/man-pages/man3/backtrace.3.html вот что есть на этот счет, это GNU экстеншен. Можно конечно и через отладчик поизвращаться как-нибудь. Думаю, идея ясна

SZT ★★★★★
()
Последнее исправление: SZT (всего исправлений: 1)
Ответ на: комментарий от SZT

Думаю, идея ясна

Не ясна. malloc/realloc не фейлится, программа работает как надо. Зачем такие извращения? Я потом вообще все проверки malloc/realloc переделаю в mymalloc в котором буду громко падать. Утечек по тому же valgrind нет. Bitching только на выделенную строку (ну и каждый раз когда используется из другой функции).

Edible
() автор топика
warehouse.elem[warehouse.elemcount - 1] = element;

А у тебя этот warehouse.elemcount может теоретически стать нулем? И тогда warehouse.elem[0-1] - не будет ли тут ошибки?

SZT ★★★★★
()
Ответ на: комментарий от i-rinat

и этому скажу — кривой у тебя код.

Мой код быстрее и оптимальнее твоего стандартного подхода - там ты выполняешь действия когда реаллок выполнился нормально, здесь - когда упал (что маловероятно и практически невероятно при малых данных).

Edible
() автор топика
Ответ на: комментарий от Edible

Идея не в том чтобы подсчитывать количество malloc/realloc и ловить утечки, а в том чтобы записывать регионы памяти, который этим malloc/realloc выделены для *index, и при попытке записи в *index просматривать эти регионы, и если адрес, по которому мы хотим записывать не значится в записях, падать и вызывать бектрейс

SZT ★★★★★
()
Ответ на: комментарий от MKuznetsov

Кстати, возможно что именно это.

Edible, какая размерность системы?

IIRC, int при вычислениях приводится к системному типу.

Т.е. фикс вида:

/* E */ typedef uint SmlIndex;
должен помочь, отцу неочевидного realloc'а. ;)

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от Edible

Мой код быстрее и оптимальнее твоего стандартного подхода

Гы-гы-гы. Попробовал написать два варианта с добавлением в int[] массив. В «твоём» варианте в ожидаемом пути оказалось на одно обращение к памяти больше (к аналогу elemcount). В принципе, не страшно, но вынуждает сбросить записи раньше, чем возможно было.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)
Ответ на: комментарий от MKuznetsov

Ну валгринд ругается описываемым в топике образом лишь в том случае, если мы записываем байтики в область памяти, в которую их записывать нельзя. Нарпимер такой код

int main(void)
{
  char *a = malloc(10);
  a[-1] = 0;
  return 0;
}
выдаст
==14599== Invalid write of size 1
==14599==    at 0x40054B: main (in /path/to/file/a.out)
==14599==  Address 0x51fc03f is 1 bytes before a block of size 10 alloc'd
==14599==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14599==    by 0x40053E: main (in /path/to/file/a.out)
==14599== 
==14599== 
А от несходящихся размерностей такого просто не может быть.
Если же может, жду конкретного тесткейса

SZT ★★★★★
()
Ответ на: комментарий от SZT

Тогда был бы invalid read, а у него write.

anonymous
()

1. Что внутри у SML_CHECKPTR?
2. printf(«%zu %p\n», sizeof(index), &index) в main()
3. printf(«%zu %p\n», sizeof(*index), index) в SmlWhsAdd() + по всему стеку выше

anonymous
()
Ответ на: комментарий от MKuznetsov

Компилеры gcc и clang на такое ругаться не умеют. Почему не умеют - вопрос не ко мне

SZT ★★★★★
()
Ответ на: комментарий от SZT

uint32_t. Не может. На создание одного элемента суммарно эдак 0.05 с. уходит. Пару лет до переполнения точно ждать.

// Moreo

anonymous
()
Ответ на: комментарий от anonymous

1.

#define SML_CHECKPTR(X)\
if (!(X)) return SML_ERR_BADPOINTER;
2-3. Посмотрю сегодня вечером.

anonymous
()
Ответ на: комментарий от Edible

Мой код быстрее и оптимальнее твоего стандартного подхода - там ты выполняешь действия когда реаллок выполнился нормально, здесь - когда упал (что маловероятно и практически невероятно при малых данных).

Преждевременная оптимизация кода, это как преждевременная эякуляция...стыдно этим годиться в общем.

anonymous
()
Ответ на: комментарий от anonymous

Не ломается. Индесы находятся в статическом массиве, который находится в SmlElement. SmlElement корректно выделяется маллоком в том же WhsAdd, если не трогать создание текстур - то valgrind молчит, т.е. в самом WhsAdd проблемы нет.

Тогда копаю глубже в сторону проблемы с widget->sprite. Но даже намека на развязку не вижу.

typedef struct
{
	SmlGeometry  geometry;
	SmlIndex     sprite[SML_THEMEBLOCK_SIZE];
	SmlIndex     theme [SML_THEMEBLOCK_SIZE];
	int32_t      state;
	SmlBool      visible;
	char *       caption;
    SmlBool      enabled;
	SmlWidgetExt ext;
} SmlWidgetData;

Вот на данный момент, я поправил все остальные сообщения, выделил только текстуры для одного объекта, получил только вот эти сообщения:
http://s16.postimg.org/f3efs5tg5/Screenshot_17_11_2015_00_29_07.png

Кроме показанного, моих сообщений нет (есть утечка в fontconfig, не моя).

Мыслей нет совсем. Доп инфа, что удалось накопать - SmlWidgetSpritesCreate вызывается только единожды, SML_THEMEBLOCK_SIZE = 0x20. Как понять на какие индексы он ругается - не знаю. Было бы неплохо это узнать - облегчило бы поиск проблемы.

Edible
() автор топика
Ответ на: комментарий от Edible

Как понять на какие индексы он ругается - не знаю. Было бы неплохо это узнать - облегчило бы поиск проблемы.

Вставил в 75ю строку printf i и слип на 10 секунд. путем переключения между окном вывода и окном анализатора выяснил что ругается показав «0». Т.е. походу сразу на первом же элементе.

Не помогло(

Edible
() автор топика
Ответ на: комментарий от Edible
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

typedef enum
{
    SML_ETYPE_NONE                = (0x000000),
    SML_ETYPE_WINDOW              = (0x000001),
    SML_ETYPE_WIDGET_FOCUSABLE    = (0x000002),
    SML_ETYPE_WIDGET_NONFOCUSABLE = (0x000003),
    SML_ETYPE_TIME                = (0x000004),
    SML_ETYPE_GRAPHICS            = (0x000005),
    SML_ETYPE_TEXTOBJ             = (0x000006),
    SML_ETYPE_GRAPHRULES          = (0x000007),
    SML_ETYPE_SHARED              = (0x000008)
} SmlElemType;

#define SML_GENERICDATASIZE  (1024) /* bytes */

typedef uint32_t SmlErrors; // simplified.
typedef uint32_t SmlIndex;

typedef struct
{
    char            data[SML_GENERICDATASIZE];
} SmlGenericData;

#define SML_THEMEBLOCK_SIZE (0x20)

typedef struct
{
    SmlIndex     sprite[SML_THEMEBLOCK_SIZE];
    SmlIndex     theme [SML_THEMEBLOCK_SIZE];
} SmlWidgetData;

typedef union
{
    SmlGenericData  gen;
    SmlWidgetData   wdg;
} SmlElemData;

typedef struct
{
    SmlElemType    type;
    SmlElemData    data;
} SmlElement;

typedef struct
{
    SmlElement   * elem;
    uint32_t       elemcount;
} Warehouse;

Warehouse warehouse;

SmlErrors SmlWhsAdd(SmlElement element, SmlIndex * index)
{
    //SML_CHECKPTR(index); Just checks if null.

    SmlElement * ptrold = warehouse.elem;

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

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

    *index = (warehouse.elemcount - 1);

    return 0;//SML_ERR_SUCCESS;
}



int main(void)
{
    // Inits in another module
    warehouse.elemcount = 0;
    warehouse.elem = NULL;

    SmlElement dummy;
    dummy.type = SML_ETYPE_WINDOW;

    SmlIndex window;
    SmlWhsAdd(dummy, &window);
    SmlElement sprite;
    sprite.type = SML_ETYPE_GRAPHICS;

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

    return 0;
}
Edible
() автор топика
Ответ на: комментарий от i-rinat

Чего?

warehouse.elem      = realloc(warehouse.elem,
                                  (++warehouse.elemcount) * sizeof(SmlElement));

1. elemcount = elemcount+1
2. sizeof() = 1030
3. realloc(elem, (elemcount+1)*1030)
4. warehouse.elem = newpointer.
Edible
() автор топика
Ответ на: комментарий от Edible

Я понял в чём у тебя ошибка.

  • line 86 — определение пустого элемента (NULL)
  • line 96 — index(!) в пустой элемент определённый выше, передача в функцию по значению
  • line 75 — запись «в никуда» по указателю на NULL

Простой патч я тебе тут не напишу. Тут всю логику передумывать надо.

beastie ★★★★★
()
Ответ на: комментарий от i-rinat

Там беда в том, что &(warehouse.elem[window].data.wdg.sprite[0]) пераётся в функцию, но при этом warehouse.elem == NULL!

ЗЫ: да, ты о том же. ;) Не заметил.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от beastie

Тут надо помнить, что это минифицированный пример. Допустим, warehouse.elem не будет равно NULL'у. Всё равно ведь берётся указатель на место в памяти, а внутри функции эта память освобождается realloc'ом. Причём благодаря тому, что делается это не каждый раз, а только когда realloc'у перестанет хватать выделенного для блока места, баг получается «плавающим».

i-rinat ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.