我的程序需要用压缩解压缩,我找了个7ZIP压缩库源代码。里面没有生成LIB的,只有生成DLL,我建了个LIB工程,生成了一个在VC下建了个工程正常使用。转到汇编平台就不行了,卡死在LzmaCompress这个函数,LzmaCompress在大约230条指令的时候调用了HeapAlloc函数,就卡死在这个函数里。
PUSH ESI         ;HeapSize  ESI==5824
PUSH 8           ;Flags     HEAP_ZERO_MENORY
PUSH DWORD PTR DS:[533258]   ;hHeap
CALL DWORD PTR DS:[411018]   ;HeapAlloc
hHeap是533258地址的一个双字变量,他是0,所以进入HeapAlloc大约20个指令内就出现访问越界。
我于是跟踪VC下编译的程序进入这个函数调用,发现hHeap【533258】指向的双字不是零,是00370000,结果是可以正常使用。
我重启VC下编译的程序,在【533258】设置了内存写入断点,结果发现在main函数没有调用之前,VC初始化代码设置了【533258】,用的是HeapCreate函数返回值。
查看汇编编译的程序,一直执行到HeapAlloc出错也没有设置【533258】的值,应为汇编没有像VC编译出程序那样的初始代码,而是直接就调用了start:开始处;
我重新进入VC添加了一些代码去除了VC自动添加的初始代码:
#pragma comment(linker, "/ENTRY:EntryPoint")
void EntryPoint() 

     
     ExitProcess(main()); 

设置从EntryPoint启动,结果一样出现了在HeapAlloc出错。甚至连printf都出错在HeapAlloc。
以上的VC下是控制台工程,我建了个WIN32工程一样是出错。我怀疑是不是那个LIB使用了类似NEW一样的C++操作符,所以导致必须要初始化代码,而汇编平台无法提供。但是我看他的代码都是.c结尾的,里面却调用了一些类似C++类的东西。他代码,
p = alloc->Alloc(alloc, sizeof(CLzmaEnc));里的Alloc是objidl.h的
void *( STDMETHODCALLTYPE *Alloc )( 
            IMalloc * This,
            /* [in] */ SIZE_T cb);
以后就查不到了。objidl.h 是用來放 COM 的核心宣告用的,以及 MIDL (Microsoft Interface Definition Language)  的宣告,這些東西和 COM Automation 有很密切的關係。是不是跟这个有关系??求解! 

解决方案 »

  1.   

        c/c++的runtime里面有初始化malloc/free和new/delete函数运行时需要的相关的平台相关数据(在windows中就是要能动态扩展堆内存),这几个函数都使用了heapalloc/heapfree相关的windows Api。
        因此,如果需要在不使用c runtime初始化的工程,比如楼主的
    #pragma comment(linker, "/ENTRY:EntryPoint") 
    void EntryPoint() 

        ExitProcess(main()); 
    }
    这样的工程中使用7z,就必须
    1、手工初始化进程的堆(HeapCreate/CreateProcessHeap?实在记不清了),并且
    2、重新定义7z源代码中的malloc/free,new/delete相关函数。
    比如定义
    void *malloc(size_t n)
    {
        return HeapAlloc(GetProcessHeap(), n);
    }
    void free(void *p)
    {
        return HeaapFree(GetProcessHeap(), p);
    }
    编译时忽略所有默认库,并链接malloc/free函数的obj文件。举例:
    #pragma comment(linker, "/ENTRY:EntryPoint") 
    void EntryPoint() 
    {
        // HeapCreate() // 初始化进程堆
        void *p = malloc(1024*1024); // 进程堆没有初始化,执行失败
        free(p); 
    }
      

  2.   

    回一楼:谢谢。
    回二楼:我指的是ASM工程。
    回三楼:先谢谢你回答我的问题,我基本明白了。原来是汇编没有runtime初始化。
            这下可麻烦了当初选错了,不应该用ASM,这个压缩库也比较变态你干嘛非要用RUNTIME啊,你不会直接用WINDOWS内存管理函数。
            现在不知道如何在汇编下如何手动RUNTIME初始化!
      

  3.   

    http://bbs.pediy.com/showthread.php?t=106488
    2楼有附件LzmaLib.rar,大家帮帮我。
      

  4.   

    谢谢6楼7楼,问题解决了,LzmaLib.c里面有2个函数
    static void *SzAlloc(void *p, size_t size) { p = p; return Alloc(size); }
    static void SzFree(void *p, void *address) { p = p; Free(address); }
    static ISzAlloc g_Alloc = { SzAlloc, SzFree };
    我改成了
    static void *SzAlloc(void *p, size_t size) { p = p; return MidAlloc(size); }
    static void SzFree(void *p, void *address) { p = p; MidFree(address); }
    static ISzAlloc g_Alloc = { SzAlloc, SzFree };
    (孤陋寡闻了,还是第一次看到结构体成员是函数)
    下面的2个函数MidAlloc,MidFree函数体用的是
    VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
    VirtualFree(address, 0, MEM_RELEASE);
    而不是用malloc(size);free(address);
    成功了,不调用RUNTIME函数,不会出现内存违规访问了。但是汇编不能用VC下编写的程序的RUNTIME还是个问题啊?!另外说一下,http://www.7-zip.org/sdk.html有下载LZMA压缩解压缩算法的代码C,C++,JAVA的都有,有需要压缩解压缩的可以去看看。
      

  5.   

    不能用是不是因为VC下编译的问题啊,比方说函数标号,
    _fun@12不兼容?