VerySource

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 857|回复: 5

Bug还是我做错了???

[复制链接]

1

主题

4

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
发表于 2020-1-17 21:20:01 | 显示全部楼层 |阅读模式
因为需要用到MD5算法,加上本人实在是懒所以决定用Windows提供的MD5Init, MD5Update, MD5Final API来搞定,但是微软也够懒,这三个API连头文件都没提供所以我只好用LoadLibrary, GetProcAddress来搞定了。可是问题出现了,编译运行后提示:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
问题出在调用MD5Init的地方。反汇编,结果发现API函数返回的时候用了ret 4指令(MD5Init只有一个参数:指向MD5_CTX结构的指针)返回后发现VS生成的代码中加入了Add esp,4这样一条指令,ESP被错误的多加上了4个字节,因此出现了上面的问题。但是同样的代码我在用GCC3.4.4编译时却没有问题。
请问这个问题该如何解决。源代码如下:

//////////////md5.h///////////////////

#pragma once

#include <windows.h>

typedef struct _MD5_CTX
{       
        ULONG i[2];
        ULONG buf[4];
        unsigned char in[64];
        unsigned char digest[16];
} MD5_CTX;

typedef void (*PMD5Init)(
        MD5_CTX* context
);

typedef void (*PMD5Update)(
        MD5_CTX* context,
        unsigned char* input,
        unsigned int inlen
);

typedef void (*PMD5Final)(
        MD5_CTX* context
);

////////////////////////md5.cpp////////////////
#include "stdafx.h"
#include "md5.h"

void GetMD5Hash(MD5_CTX* md5)
{
        HMODULE hmodule = LoadLibrary(TEXT("Cryptdll.dll"));
        PMD5Init MD5Init = (PMD5Init)GetProcAddress(hmodule, "MD5Init");
       
        MD5Init(md5);  //就是这里!!!

        FreeLibrary(hmodule);
}


int _tmain(int argc, _TCHAR* argv[])
{
        MD5_CTX md5;

        GetMD5Hash(&md5);

        return 0;
}
回复

使用道具 举报

1

主题

4

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-1-23 12:09:01 | 显示全部楼层
貌似要用stdcall,但是应该怎么写啊
回复

使用道具 举报

1

主题

4

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-1-23 12:54:01 | 显示全部楼层
已搞定
typedef  void  (__stdcall *PMD5Init)(  
           MD5_CTX*  context  
);  

回复

使用道具 举报

0

主题

1

帖子

2.00

积分

新手上路

Rank: 1

积分
2.00
发表于 2020-1-23 19:45:01 | 显示全部楼层
神速.替楼主高兴.
回复

使用道具 举报

0

主题

70

帖子

42.00

积分

新手上路

Rank: 1

积分
42.00
发表于 2020-1-24 13:54:01 | 显示全部楼层
因为调用方式的原因很多人都出现了相似的问题,再次记下了希望自己以后不犯同样的错误!
回复

使用道具 举报

1

主题

4

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-1-26 22:18:01 | 显示全部楼层
开始的时候查了半天的MSDN,查来查去都不知道那个__stdcall在用typedef的时候应该插在哪儿,然后就以为可能不用加也行吧,结果就出错了。后来上网搜了一下,发现cdcel和stdcall的区别就在于一个是由调用者一个是由被调用者清理堆栈,看来一定是要用stdcall了,想了半天才想到,typedef void __stdcall *PMD5Init不行可以这样啊typedef  void  (__stdcall *PMD5Init),果真不出我所料,这次就成功了~呵呵,谢谢各位了~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|CopyRight © 2008-2023|verysource.com ( 京ICP备17048824号-1 )

快速回复 返回顶部 返回列表