LINUX.ORG.RU

Вопрос по uthash под офтопиком

 , uthash


0

3

Пишу небольшую сишную софтину. Использую в ней библиотеку uthash. Потом под своим уютным Linux кросскомпилирую под винду. В итоге что я получаю? Под Wine всё работает, под виндой падает. Запустил под виндовым GDB - увидел, что падает всегда на вызовах uthash. Точнее не просто на uthash, а на вызовах calloc из msvcrt. Начал грешить на обращения за пределами выделенной памяти, которые разрушают структуры менеджера памяти из libc (как известно, информация о блоке памяти обычно хранится около самого выделенного блока). Прогнал под valgrind под Wine на Linux - никаких ошибок не выявлено (ни утечек, ни некорректных обращений). Под винду valgrind не нашёл, однако нашёл некий drmemory - и он обнаружил кучу обращений за пределами выделенной памяти. Причём все - внутри кода uthash.

Вот всё обращения к API uthash, которые есть в моём коде:

typedef struct WaitingObjectInfo {
	HANDLE handle;
	WaitingObjectCallback callback;
	void *data;
	UT_hash_handle hh;
} WaitingObjectInfo;

WaitingObjectInfo *waiting_object_list = NULL;
size_t waiting_object_count = 0;
... блок 1 ...
	HANDLE handle_list[waiting_object_count];
	WaitingObjectInfo *info, *tmp_info;
	size_t i = 0;
	HASH_ITER(hh, waiting_object_list, info, tmp_info) {
		handle_list[i++] = info->handle;
	}
	assert(i == waiting_object_count);
... блок 2 ...
	if ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + waiting_object_count))) {
		HANDLE handle = handle_list[result - WAIT_OBJECT_0];
		HASH_FIND_INT(waiting_object_list, &handle, info);
		assert(info != NULL);
		if (info->callback) {
			info->callback(info->data, info->handle);
		}
	}
... блок 3 ...
	WaitingObjectInfo *info, *tmp_info;
	HASH_ITER(hh, waiting_object_list, info, tmp_info) {
		HASH_DEL(waiting_object_list, info);
		free(info);
	}
	waiting_object_count = 0;
... блок 4 ...
	WaitingObjectInfo *info;
	HASH_FIND_INT(waiting_object_list, &handle, info);
	if (!info) {
		info = malloc(sizeof(WaitingObjectCallback));
		assert((info != NULL) && "malloc for WaitingObjectInfo failed");
		info->handle = handle;
		HASH_ADD_INT(waiting_object_list, handle, info);
		waiting_object_count++;
	}
	info->callback = callback;
	info->data = data;
... блок 5 ...
	WaitingObjectInfo *info;
	HASH_FIND_INT(waiting_object_list, &handle, info);
	if (info) {
		HASH_DEL(waiting_object_list, info);
		free(info);
		waiting_object_count--;
	} else {
		fprintf(stderr, "[WARNING] remove_waiting_object: handle %i not in waiting list!\n", handle);
	}	

Код строго однопоточный (во всяком случае нигде в своём приложении я не создаю потоки), блок 1 и блок 2 находятся в одной функции и выполняются строго последовательно (остальные блоки не могут быть вызваны между ними).

Никогда не падает на HASH_FIND_INT, некорректные обращения находятся в блоке 3 и 4 (блок 5 пока нигде не используется), при этом внутри макросов добавления/удаления элекментов. Падает либо внутри функции добавления на calloc, либо при удалении, либо на free(info) после удаления.

Кросскомпилирую командой:

i686-w64-mingw32-gcc -c -o имя-файла.o -O2 -ggdb -Iuthash/src имя-файла.c

Затем линкую командой:

i686-w64-mingw32-gcc -o имя-файла.exe имя-файла.o -lm -static

Я бы мог грешить на баг в uthash, но почему под Linux некорректных обращений к памяти не происходит (под данным valgrind)?

Linux тут при том, что Wine я запускаю под Linux.

★★★★★

Берёшь рантайм информацию о фреймах стэка под GDB и находишь причину падения. Иногда помогает отладочные записи в терминал. За тебя твой код никто не отдебажит.

А от виндово-сишной лапши глаза вытекают.

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

Там от винды по факту только пара констант, да HANDLE. Можешь мысленно HANDLE заменить на int, смысл не изменится.

Остальное это обычный libc (malloc, free) и uthash. И падает оно внутри HASH_ADD_INT. И я даже знаю почему - из-за обращений за границы выделенной памяти. Однако под Linux под Wine всё работает.

KivApple ★★★★★
() автор топика

Замени uthash на свою собственную хеш таблицу. Если баги пропадут, маякни разрабам uthash и используй другую хеш-таблицу(или может быть будет достаточно своей реализации). Иначе если проблема сохранится, ты сможешь точно узнать где падает и найти ошибку.

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

Попробуй определить свой макрос uthash_malloc(_size) и продебажь, где и сколько памяти оно выделяет, и успешно ли это было.

joy4eg ★★★★★
()

А если собрать на винде с помощью MSVS?

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