Собственно, вот код: Код (Text): #include <stdio.h> #include <stdlib.h> #include <string.h> #include <direct.h> #include "zlib/zlib.h" #pragma comment(lib, "zlib/zdll.lib") #pragma pack(push, 1) typedef struct { char version[12]; long files_count; long dirs_count; long packed_size; } VDKHEADER; typedef struct { char type; char name[128]; long size; long packed_size; long content; long next; } VDKRECORD; #pragma pack(pop) FILE *vdk_file; void unpack_dir(long offset, const char *dst_dir) { long cur_offset = offset; VDKRECORD rec; char dst_file_name[_MAX_PATH]; while (cur_offset) { fseek(vdk_file, cur_offset, SEEK_SET); fread(&rec, sizeof(rec), 1, vdk_file); if (strcmp(rec.name, ".") && strcmp(rec.name, "..")) { strcpy_s(dst_file_name, _countof(dst_file_name), dst_dir); strcat_s(dst_file_name, _countof(dst_file_name), "\\"); strcat_s(dst_file_name, _countof(dst_file_name), rec.name); switch (rec.type) { case 0: { FILE *dst_file; unsigned long unpacked_size = rec.size, packed_size = rec.packed_size; void *unpacked_buf = malloc(unpacked_size); void *packed_buf = malloc(packed_size); printf("Found file: %s\n", rec.name); printf("Size: %d\n", unpacked_size); printf("Packed size: %d\n\n", packed_size); if (fread(packed_buf, 1, packed_size, vdk_file) == packed_size) { uncompress(unpacked_buf, &unpacked_size, packed_buf, packed_size); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< fopen_s(&dst_file, dst_file_name, "wb"); fwrite(unpacked_buf, 1, unpacked_size, dst_file); fclose(dst_file); } free(unpacked_buf); free(packed_buf); break; } case 1: { printf("Found directory: %s\n", rec.name); _mkdir(dst_file_name); unpack_dir(rec.content, dst_file_name); break; } } } cur_offset = rec.next; } } int main(int argc, char *argv[]) { VDKHEADER hdr; char *vdk_file_name = "D:\\Games\\RequiemRus\\data\\DAT.VDK"; char *dst_dir_name = "D:\\RQ"; if (fopen_s(&vdk_file, vdk_file_name, "rb") == 0) { printf("Archive:\t%s\n", vdk_file_name); if (fread(&hdr, sizeof(hdr), 1, vdk_file) == 1) { printf("Version:\t%s\n", hdr.version); printf("Files count:\t%d\n", hdr.files_count); printf("Dirs count:\t%d\n", hdr.dirs_count); printf("Size:\t\t%.2f MB\n\n", (float)hdr.packed_size/1024/1024); unpack_dir(sizeof(VDKHEADER), dst_dir_name); } fclose(vdk_file); } argc; argv; return 0; } В Debug сборке всё работает прекрасно, переключаю на Release и ловлю исключение ACCESS VIOLATION где-то в недрах zlib.uncompress. Отчего такое может происходить? Линковка с zlib динамическая. MSVS 2005 SP1, все параметры по-умолчанию (ну за исключением /TC /D "_MBCS") Debug версия собирается с Multi-threaded Debug DLL (/MDd), Release версия - с Multi-threaded DLL (/MD). Пробовал менять - результат - нулевой.
а что в стеке валидные параметры ? жди пока упадет клик по нужной функции в call stack потом в memory вбиваеш ebp (именно буквами вписываеш в поле address) формат вывода 4 байта ставиш и все указывать будет на сохраненный ebp за ним адрес возврата и параметры следом вот пример для puts 0x0013FF10 0013ff68 00411304 00415d20
Попробовал трассировать uncompress: Код (Text): 00402188 push esi 00402189 push edi 0040218A lea ecx,[esp+18h] 0040218E push ecx 0040218F push ebx 00402190 call _uncompress (401000h) ... _uncompress: 00401000 jmp dword ptr ds:[400000h] 00401006 nop 00401007 nop ... 00905A4D ??? 00905A4E ??? 00905A4F ??? Собственно, всё понятно, откуда access violation. Не понятно как так линкер слинковал, и что делать
можно попробовать добавить __declspec(dllimport) тогда вызов напрямую будет генерировать без jmp'а вот в release VS2008 без __declspec(dllimport) генерирует через jmp как у Вас Код (Text): extern "C" void __stdcall SetConsoleTitleA(const char*); Код (Text): 00401002 BE FC 20 40 00 mov esi,4020FCh 00401007 56 push esi 00401008 E8 97 0A 00 00 call 00401AA4 ... 00401AA4 FF 25 34 20 40 00 jmp dword ptr ds:[402034h] ... _SetConsoleTitleA@4: 7C870711 6A 0C push 0Ch 7C870713 68 70 07 87 7C push 7C870770h а вот с __declspec(dllimport) в описании вызов без jmp'а Код (Text): extern "C" __declspec(dllimport) void __stdcall SetConsoleTitleA(const char*); Код (Text): 00401002 BE FC 20 40 00 mov esi,4020FCh 00401007 56 push esi 00401008 FF 15 34 20 40 00 call dword ptr ds:[402034h] ... _SetConsoleTitleA@4: 7C870711 6A 0C push 0Ch 7C870713 68 70 07 87 7C push 7C870770h
И всё же не ясно такое поведение линкера. Простейший код: Код (Text): int main(void) { uncompress(0, 0, 0, 0); } В Debug версии всё собирается нормально. В Release zlib1.dll в импорте есть, но из неё не импортируется uncompress, т.е. ничего не импортируется. Как это объяснить?
Видимо дело в кривом *.lib файле... Заменил этот файл из пакета на свой сгенерированный из *.def и всё заработало. Весьма странно, библиотека популярная, гугль молчит про мою ситуацию.
wsd Нету. После ребилда lib файла всё заработло. Кстати, размер его уменшьился с 38 кБ до 13 кБ, и исчезло предупреждение '.text' sections have different attributes 0xXXXXXXXX или как-то так.