windows函数入口问题

操作系统装载应用程序后,做完初始化工作就转到程序的入口点执行。程序的默认入口点由连接程序设置, 不同的连接器选择的入口函数也不尽相同。在VC++下,连接器对控制台程序设置的入口函数是 mainCRTStartup,mainCRTStartup 再调用main 函数;对图形用户界面(GUI)程序设置的入口函数是 WinMainCRTStartup,WinMainCRTStartup 调用你自己写的 WinMain 函数。具体设置哪个入口点是由连接器的“/subsystem:”选项确定的,它告诉操作系统如何运行编译生成的.EXE文件。可以指定四种方式:CONSOLE|WINDOWS|NATIVE|POSIX。如果这个选项参数的值为 WINDOWS,则表示该应用程序运行时不需要控制台,有关连接器参数选项的详细说明请参考 MSDN 库。

以下四种组合,可以实现console和windows模式的混合,可以达到不弹出DOS窗口的效果,也可以达到在Windows程序中向控制台输出printf信息的目的。
#pragma comment( linker, "/subsystem:windows /entry:WinMainCRTStartup" )
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
#pragma comment( linker, "/subsystem:console /entry:mainCRTStartup" )
#pragma comment( linker, "/subsystem:console /entry:WinMainCRTStartup" )

也可以在Project Settings里的Link标签里的Project Options里的最后添加下面之一:
/ENTRY:mainCRTStartup
/ENTRY:wmainCRTStartup
/ENTRY:WinMainCRTStartup
/ENTRY:wWinMainCRTStartup
它们对应的入口函数分别是main,wmain,WinMain,wWinMain
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR      lpCmdLine,
int        nCmdShow)
{
      // ...
}

int main(void)
{
      // ...
}

2) UNREFERENCED_PARAMETER的用处

作用:告诉编译器,已经使用了该变量,不必检测警告!

在VC编译器下,如果您用最高级别进行编译,编译器就会很苛刻地指出您的非常细小的警告。当你生命了一个变量,而没有使用时,编译器就会报警告:

“warning C4100: ''XXXX'' : unreferenced formal parameter.”

所以,为了让编译器不必检测你的警告,就使用UNREFERENCED_PARAMETER语句。比如:

int SomeFunction(int arg1, int arg2)
{
  UNREFERENCED_PARAMETER(arg2)
  ...
}

===============================================================================

 
 文档 代码工具 

翻译文档 本文适合中级读者 已阅读9439次 ]  

C++ At Work 专栏...
未引用参数,添加任务栏命令及其它...

原著:Paul DiLascia
翻译:NorthTibet

下载源代码:CAtWork0505.exe(171KB) 
原文出处:Unreferenced Parameters, Adding Task Bar Commands, and More

未引用参数
添加任务栏命令

 我看到过一些 C++ 代码针对没有使用过的参数用 UNREFERENCED_PARAMETER,例如:

int SomeFunction(int arg1, int arg2) { UNREFERENCED_PARAMETER(arg2) ... }

我还看到过这样的代码:

int SomeFunction(int arg1, int /* arg2 */) { ... }

你能解释它们的差别吗?哪一种用法更好?

Judy McGeough

 是啊!为什么呢?让我们从 UNREFERENCED_PARAMETER 开始吧。这个宏在 winnt.h 中定义如下:

#define UNREFERENCED_PARAMETER(P) (P)

  换句话说 UNREFERENCED_PARAMETER 展开传递的参数或表达式。其目的是避免编译器关于未引用参数的警告。许多程序员,包括我在内,喜欢用最高级别的警告 Level 4(/W4)进行编译。Level 4 属于“能被安全忽略的事件”的范畴。虽然它们可能使你难堪,但很少破坏你的代码。例如,在你的程序中可能会有这样一些代码行:

int x=1;

  但你从没用到过 x。也许这一行是你以前使用 x 时留下来的,只删除了使用它的代码,而忘了删除这个变量。Warning Level 4 能找到这些小麻烦。所以,为什么不让编译器帮助你完成可能是最高级别的专业化呢?用Level 4 编译是展示你工作态度的一种方式。如果你为公众使用者编写库,Level 4 则是社交礼节上需要的。你不想强迫你的开发人员使用低级选项清洁地编译他们的代码。
  问题是,Level 4 实在是太过于注意细节,在 Level 4 上,编译器连未引用参数这样无伤大雅的事情也要抱怨(当然,除非你真的有意使用这个参数,这时便相安无事)。假设你有一个函数带来两个参数,但你只使用其中一个:

int SomeFunction(int arg1, int arg2) { return arg1+5; }

使用 /W4,编译器抱怨:

“warning C4100: ''arg2'' : unreferenced formal parameter.”

为了骗过编译器,你可以加上 UNREFERENCED_PARAMETER(arg2)。现在编译器在编译你的引用 arg2 的函数时便会住口。并且由于语句:

arg2;

实际上不做任何事情,编译器不会为之产生任何代码,所以在空间和性能上不会有任何损失。

  细心的人可能会问:既然你不使用 arg2,那当初为何要声明它呢?通常是因为你实现某个函数以满足某些API固有的署名需要,例如,MFC的 OnSize 处理例程的署名必须要像下面这样:

void OnSize(UINT nType, int cx, int cy);

  这里 cx/cy 是窗口新的宽/高,nType 是一个类似 SIZE_MAXIMIZED 或 SIZE_RESTORED 这样的编码,表示窗口是否最大化或是常规大小。一般你不会在意 nType,只会关注 cx 和 xy。所以如果你想用 /W4,则必须使用 UNREFERENCED_PARAMETER(nType)。OnSize 只是上千个 MFC 和 Windows 函数之一。编写一个基于 Windows 的程序,几乎不可能不碰到未引用参数。
  说了这么多关于 UNREFERENCED_PARAMETER 内容。Judy 在她的问题中还提到了另一个 C++ 程序员常用的并且其作用与 UNREFERENCED_PARAMETER 相同的诀窍,那就是注释函数署名中的参数名:

void CMyWnd::OnSize(UINT /* nType */, int cx, int cy) { }

  现在 nType 是未命名参数,其效果就像你敲入 OnSize(UINT, int cx, int cy)一样。那么现在的关键问题是:你应该使用哪种方法——未命名参数,还是 UNREFERENCED_PARAMETER?
  大多数情况下,两者没什么区别,使用哪一个纯粹是风格问题。(你喜欢你的 java 咖啡是黑色还是奶油的颜色?)但我认为至少有一种情况必须使用 UNREFERENCED_PARAMETER。假设你决定窗口不允许最大化。那么你便禁用 Maximize 按钮,从系统菜单中删除,同时阻止每一个用户能够最大化窗口的操作。因为你是偏执狂(大多数好的程序员都是偏执狂),你添加一个 ASSERT (断言)以确保代码按照你的意图运行:

void CMyWnd::OnSize(UINT nType, int cx, int cy) { ASSERT(nType != SIZE_MAXIMIZE); ... // use cx, cy }

  质检团队竭尽所能以各种方式运行你的程序,ASSERT 从没有弹出过,于是你认为编译生成 Release 版本是安全的。但是此时 _DEBUG 定义没有了,ASSERT(nType != SIZE_MAXIMIZE)展开为 ((void)0),并且 nType 一下子成了一个未引用参数!这样进入你干净的编译。你无法注释掉参数表中的 nType,因为你要在 ASSERT 中使用它。于是在这种情况下——你唯一使用参数的地方是在 ASSERT 中或其它 _DEBUG 条件代码中——只有 UNREFERENCED_PARAMETER 会保持编译器在 Debug 和 Release 生成模式下都没有问题。知道了吗?
  结束讨论之前,我想还有一个问题我没有提及,就是你可以象下面这样用 pragma 指令抑制单一的编译器警告:

#pragma warning( disable : 4100 )

4100 是未引用参数的出错代码。pragma 抑制其余文件/模块的该警告。用下面方法可以重新启用这个警告:

#pragma warning( default : 4100 )

  不管怎样,较好的方法是在禁用特定的警告之前保存所有的警告状态,然后,等你做完之后再回到以前的配置。那样,你便回到的以前的状态,这个状态不一定是编译器的默认状态。
  所以你能象下面这样在代码的前后用 pragma 指令抑制单个函数的未引用参数警告:

#pragma warning( push ) #pragma warning( disable : 4100 ) void SomeFunction(...) { } #pragma warning( pop )

  当然,对于未引用参数而言,这种方法未免冗长,但对于其它类型的警告来说可能就不是这样了。库生成者都是用 #pragma warning 来阻塞警告,这样他们的代码可以用 /W4 进行清洁编译。MFC 中充满了这样的 pragmas 指令。还有好多的 #pragma warning 选项我没有在本文讨论。有关它们的信息请参考相关文档。

 我注意到一些应用程序,当右键单击其任务栏最小化按钮时,在弹出的上下文菜单中具备特殊的命令。例如,WinAmp(一个流行的媒体播放器)有一个附加的 “WinAmp”菜单项,其中是 WinAmp 特有的命令。我如何在程序的任务栏按钮中添加我自己的菜单项?

Jirair Osygian

 我创建了一个简单的 MFC SDI 程序,该程序用表单视图(Form View)显示一个计数器。我想通过右键单击任务栏上程序的最小化按钮来控制启动/停止这个计数器。在表单视图上通过按钮控制的启动/停止功能运行正常,我也能将启动/停止命令加到系统菜单。但我单击加入的系统菜单时没反应。我如何处理这些定制的系统菜单消息?

Monicque Sharman

 我两个问题一起回答,Jirair 问题的答案很简单:当你右键单击任务栏上应用程序的最小化按钮时,用户看到的菜单与用户单击左上角应用程序标题栏图标或按 Alt+Space 所看到的菜单一样。如 Figure 1 所示。这个菜单被称为系统菜单,其中包括命令如:还原、最小化、最大化和关闭等。


Figure 1 系统菜单

  你可以调用 ::GetSystemMenu 来获得此系统菜单,然后可以添加、删除或修改菜单项。你甚至可以通过关掉 WS_SYSMENU 窗口创建式样标志或 PreCreateWindow 虚函数来完全屏蔽掉这个系统菜单。但不论你做什么,当用户右键单击任务栏上应用程序的最小化按钮时,这个系统菜单还是会显示出来的。
  到了 Monicque 的问题:如果在系统菜单中添加自己的命令,MFC 是如何处理它们的呢?如果按常规来做 ——在某个地方写一个 ON_COMMAND 处理器并将它加到消息映射中,你会发现你的处理器不起作用,怎么会这样呢?
  那是因为 Windows 和 MFC 处理系统命令的方式与处理普通菜单命令的方式不一样。当用户调用窗体中的常规菜单命令或按钮时,Windows 向主窗口发送一个 WM_COMMAND 消息。如果你使用 MFC,那么其命令路由机制将捕获此消息并通过操作系统将它路由到该命令的 ON_COMMAND 命令处理器对象。(有关 MFC 命令处理机制的详细内容,参见我在 MSJ 1995年7月发表的文章:“Meandering Through the Maze of MFC Message and Command Routing”)。
  然而系统命令不属于 WM_COMMAND 消息范围。而属于另外一个叫做——WM_SYSCOMMAND 的消息。不论命令ID是真正的系统命令如 SC_MINIMIZE 和 SC_CLOSE,还是你自己添加的其它命令ID都是如此。为了处理系统菜单命令,你必须处理显式处理 WM_SYSCOMMAND 并且要选择你自己的命令 IDs。这就需要你在主窗口消息映射中添加ON_WM_SYSCOMMAND,它有一个处理函数如下:

CMainFrame::OnSysCommand(UINT nID, LPARAM lp) { if (nID==ID_MY_COMMAND) { ... // 处理它 return 0; } // 传递到基类:这一步很重要! return CFrameWnd::OnSysCommand(nID, lp); }

  如果该命令不是你的,不要忘了将它传递到你的基类处理——典型地,那就是 CFrameWnd 或 CMDIFrameWnd。否则,Windows 将无法得到此消息,并且会破坏内建的命令。
  在主框架中处理 WM_SYSCOMMAND 固然可以,但这样做感觉太业余。为什么要用特殊的机制来处理呢?就因为它们是系统菜单吗?如果你想在视图或文档对象中处理系统命令会怎样呢?有一个常见的命令放到了系统菜单中,它就是“关于”(ID_APP_ABOUT),大多数 MFC 程序都是在应用程序对象中处理 ID_APP_ABOUT:

void CMyApp::OnAppAbout() { static CAboutDialog dlg; dlg.DoModal(); }

  MFC 一个真正很酷的特性是它的命令路由系统,它使得象 CMyApp 这样的非窗口对象也能处理菜单命令。许多程序员甚至都不了解怎么会有这样的例外。如果你已经在应用程序对象中处理 ID_APP_ABOUT,那把ID_APP_ABOUT 添加到系统菜单后,为什么还要去实现一套单独的机制?
  处理外加系统命令的比较好的,或者说更 MFC 的方法应该是通过常规的命令路由机制传递它们。然后按 MFC 常规方法编写 ON_COMMAND 处理例程来处理系统命令。你甚至可以用 ON_UPDATE_COMMAND_UI 来更新你的系统菜单项,例如禁用某个菜单项或在菜单项旁边显示一个检讫标志。
  Figure 2 是我写的一个类,CSysCmdRouter,这个类将系统命令转成常规命令。为了使用这个类,你要做的只是在主框架中实例化 CSysCmdRouter,并从 OnCreate 中调用其 Init 方法即可:

int CMainFrame::OnCreate(...) { // 将我的菜单项添加到系统菜单 CMenu* pMenu = GetSystemMenu(FALSE); pMenu->AppendMenu(..ID_MYCMD1..); pMenu->AppendMenu(..ID_MYCMD2..); // 通过 MFC 路由系统命令 m_sysCmdHook.Init(this); return 0; }

  一旦你调用 CSysCmdRouter::Init,你便可以按常规方式处理 ID_MYCMD1 和 ID_MYCMD2,为 MFC 命令路由机制中的任何对象编写 ON_COMMAND 处理例程——视图,文档,框架,应用程序或通过改写 OnCmdMsg 添加的任何其它命令对象。CSysCmdRouter 还让你用 ON_UPDATE_COMMAND_UI 处理器更新系统菜单。唯一要注意的是确保命令IDs不要与其它菜单命令(除非他们确实代表相同的命令)或内建系统命令发生冲突,内建系统命令从 SC_SIZE = 0xF000 开始。Visual Studio .NET 指定的命令 IDs 从 0x8000 = 32768 开始,所以如果你让 Visual Studio 来指定 IDs,只要不超过 0xF000-0x8000 = 0x7000 个命令即可。也就是十进制的 28,762。如果你的应用程序有超过 28000 个命令,那么你需要咨询编程精神病专家。
  CSysCmdRouter 是如何实现其魔法的呢?简单:它使用我那个以前专栏中无处不在的 CSubclassWnd。CSubclassWnd 使你不用从其派生便能子类化 MFC 窗口对象。CSysCmdRouter 派生自 CSubclassWnd 并使用它子类化主框架。尤其是它截获发送到框架的 WM_SYSCOMMAND 消息。如果命令 ID 属于系统命令(大于 SC_SIZE = 0xF000),则 CSysCmdRouter 沿着 Windows 一路传递该消息;否则便吃掉 WM_SYSCOMMAND 并重新将它作为 WM_COMMAND 发送,于是 MFC 按照其常规路由过程,调用你的 ON_COMMAND 处理器。很聪明,是不是?
  那么 ON_UPDATE_COMMAND_UI 处理器呢?CSysCmdRouter 是如何让它处理系统菜单命令的呢?很简单。就在 Windows 显示菜单前,他向你的主窗口发送一个 WM_INITMENUPOPUP 消息。这是你更新菜单项的最佳时机——启用或禁用它们,添加检讫标志等等。MFC 为每个菜单项创建一个 CCmdUI 对象并将它传递到你的消息映射中相应的 ON_UPDATE_COMMAND_UI 处理器。以它为参数的 MFC 函数是 CFrameWnd::OnInitMenuPopup,这个函数是这样的:

void CFrameWnd::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu) { if (bSysMenu) return; // don''t support system menu ... }

  MFC 初始化系统菜单时不做任何事情。为什么要去关心这种事呢?万一你要让 bSysMenu 为 FALSE,即使是系统菜单,那该怎么办?这恰恰是 CSysCmdRouter 做的事情。它截取 WM_INITMENUPOPUP 并清除 bSysMenu 标志,也就是 LPARAM 的 HIWORD:

if (msg==WM_INITMENUPOPUP) { lp = LOWORD(lp); // (set HIWORD = 0) }

  现在,当 MFC 获得 WM_INITMENUPOPUP,它认为该菜单是常规菜单。只要你的命令 IDs 与真正的系统菜单不冲突,一切都运行得很好。如果你改写 OnInitMenuPopup,唯一丢失的东西是不能从主窗口菜单中区分系统菜单。嘿,你不能什么都想要!通过改写 CWnd::WindowProc,你总是能处理 WM_INITMENUPOPUP 的,或你想要区分,就比较 HMENUs。但你确实不用关心命令来自何处。


Figure 3 任务栏菜单

  为了展示所有的实践,我写了一个小测试程序: TBMenu。如图 Figure 3 所示,当你右键单击任务栏上 TBMenu 的最小化按钮,便会显示出菜单。你可以看到在菜单底部有两个额外的命令。TBMenu 的 CMainFrame代码如Figure 4 所示。便知道在 OnCreate 的什么地方添加命令并在 CMainFrame 的消息映射中用 ON_COMMAND 以及 ON_UPDATE_COMMAND_UI 处理器处理它们。TBMenu 在其应用程序类中处理 ID_APP_ABOUT(代码未列出)。CSysCmdRouter 使系统命令的工作机制类似其它命令。

说到命令,我们来看看一个小资料:

  在我一月份的专栏中,我问是否有人知道 Ctrl+Alt+Del 的由来。显然,有几个读者知道如何使用 Google,因为他们发给我的是相同的链接:《今日美国》上的一篇文章:“Thank this guy for 'control-alt-delete'”,我在一月发问之前就发现了这篇文章。Ctrl+Alt+Del 是由一个名叫 David J. Bradley 的人发现的,他在 IBM 工作过。
IBM 觉得应该有一种方法不用关闭电源就能重置(reset)其新的 PC 机。为什么要专门用 Ctrl+Alt+Del 这三个键呢?从技术上来说,David 需要使用两个修饰键。他想要一种没有人可能意外敲入的键组合。所以他选择了
Ctrl+Alt 作为修饰键(比 Shift 用得少)和 Delete,此键位于键盘的另一端,所以敲击 Ctrl+Alt+Del 需要两只手,至少在过去是这样做的。
当今现代键盘在右边也有 Ctrl 和 Alt 键。重启特性的初衷是为 IBM 的人设计的秘密安全出口,但不可避免地,它已经成为一个不是秘密的秘密。一旦开发人员知道了它,他们便开始告诉客户使用这个特性来解决机器挂起问题。随着历史的发展,Ctrl+Alt+Del 被人们亲切地成为“三指敬礼”,即便是在当今的 Windows 中仍然具有生命力,用它调出任务管理器,以便你能杀死挂起的任务或终止系统(更多有关类似 Ctrl+Alt+Del 安全键序列的内容,参见本月的Security Briefs 专栏)。那么,如果 Ctrl+Alt+Del 失败了怎么办?为什么会失败,请按住它保持 5 秒钟。
  David Bradley 是当初建立 IBM 个人计算机的 12 个工程师之一。他编写了 ROM BIOS,有关 David 的简介,参见 David J. Bradley。

祝编程愉快!

您的提问和评论可发送到 Paul 的信箱:cppqa@microsoft.com

 作者简介
  Paul DiLascia
 是一名自由作家,顾问和 Web/UI 设计者。他是《Writing Reusable Windows Code in C++》书(Addison-Wesley, 1992)的作者。通过http://www.dilascia.com 可以获得更多了解。
本文出自 MSDN Magazine 的May 2005 期刊,可通过当地报摊获得,或者最好是 订阅

3) _tWinMain与wWinMain又有什么区别呢

MFC封装了WIN API.大家都知道.但是MFC应用程序的真正流程又有多少人知道呢? 
下面就是我对MFC启动代码的一些剖析.

在TCHAR.H里,有这么2小段define.通过我的简化,我们可以看到:

//TCHAR.H 
#ifdef _UNICODE 
#define _tWinMain wWinMain 
#else 
#define _tWinMain WinMain 
#endif

   由于为了支持UNICODE,C运行库对WinMain其实区分了UNICODE版和ANSI版.对UNICODE版的程序,C运行库将调用wWinMain,而对于ANSI版的应用,则调用WinMain.这是第一点.

   然后,其实MFC的代码设计时是自动支持UNICODE的,所以,MFC的WinMain在APPMODUL.CPP被定义为
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
   这样以一来,无论用户#define _UNICODE与否,MFC的WinMain都会被调用.接下来,_tWinMain的实际运作如下:

extern "C" int WINAPI 
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
LPTSTR lpCmdLine, int nCmdShow) 

// call shared/exported WinMain 
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); 
}

   这样,AfxWinMain就和MFC挂上了钩.甚至在PETER NORTON的书中,都仅讲到了AfxWinMain乃是MFC的WinMain,但是,NORTON同志看来没有讲述清楚这点.因为,WinMain仍然是WinMain,C运行库并没有因为MFC的存在而重新设计AfxWinMain的入口.
在MS的AfxWinMain(WINMAIN.CPP)里我们可以看到如下代码: 
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
LPTSTR lpCmdLine, int nCmdShow) 

ASSERT(hPrevInstance == NULL); 
int nReturnCode = -1; 
CWinThread* pThread = AfxGetThread(); 
CWinApp* pApp = AfxGetApp();

// AFX internal initialization 
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)) 
goto InitFailure;

// App global initializations (rare) 
if (pApp != NULL && !pApp->InitApplication()) 
goto InitFailure;

// Perform specific initializations 
if (!pThread->InitInstance()) 

if (pThread->m_pMainWnd != NULL) 

TRACE0("Warning: Destroying non-NULL m_pMainWnd/n"); 
pThread->m_pMainWnd->DestroyWindow(); 

nReturnCode = pThread->ExitInstance(); 
goto InitFailure; 

nReturnCode = pThread->Run();

InitFailure: 
#ifdef _DEBUG 
// Check for missing AfxLockTempMap calls 
if (AfxGetModuleThreadState()->m_nTempMapLock != 0) 

TRACE1("Warning: Temp map lock count non-zero (%ld)./n", 
AfxGetModuleThreadState()->m_nTempMapLock); 

AfxLockTempMaps(); 
AfxUnlockTempMaps(-1); 
#endif

AfxWinTerm(); 
return nReturnCode; 
}

windows函数入口问题 UNREFERENCED_PARAMETER的用处 _tWinMain与wWinMain又有什么区别相关推荐

  1. Win32编程-头文件与函数入口

    #include <windows.h> //#include <tchar.h>int WINAPI WinMain(HINSTANCE hInstance, HINSTAN ...

  2. 【Android 逆向】函数拦截实例 ( ② 插桩操作 | 保存实际函数入口 6 字节数据 | 在插桩的函数入口写入跳转指令 | 构造拼接桩函数 )

    文章目录 前言 一.函数拦截需要的几个参数 二.插桩前先保存实际函数入口 6 字节数据 三.在插桩的函数入口写入跳转指令 | 构造拼接桩函数 前言 [Android 逆向]函数拦截实例 ( 函数拦截流 ...

  3. 【Flutter】Dart 技巧 ( 独立主函数入口 | 可空类型判定 | 默认值设定 )

    文章目录 一.独立主函数入口 二.可空类型判定 三.默认值设定 四.完整代码示例 五. 相关资源 一.独立主函数入口 在 dart 文件中声明 main() 函数 , 即可脱离 Flutter 环境 ...

  4. Windows函数错误处理

    当调用一个Windows函数时,它首先要检验传递给它的各个参数的有效性,然后再设法执行任务.如果传递一个无效参数,或者由于某种原因无法执行这项操作,那么操作系统就会返回一个值,指明该函数在某种程度上运 ...

  5. caffe函数入口caffe.cpp详解

    概览 这篇博客解析caffe函数入口caffe.cpp,主要内容为caffe启动框架,基本不涉及深度学习的具体内容,内容十分基础,适合新手阅读.下面所有的代码解析都以训练lenet手写数字体识别为例, ...

  6. Windows程序入口

    程序入口 标准的Windows程序入口 #include<windows.h>int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPre ...

  7. d3d透视逆向篇:第6课 通过特征码定位D3D函数入口地址

    本逆向安全章节是我业余之间编写的,也借鉴了前辈的经验来给大家做一个简单的文字逆向安全教程,欢迎大家讨论和指正,共同学习.禁止非法用途.教程我从最简单的开始给大家做一个简单的讲解d3d 类的3d游戏和f ...

  8. Javascript防抖函数节流函数的介绍(最详细)、彻底搞懂防抖节流的区别以及使用第三方库的防抖节流函数

    文章目录 1.防抖节流函数介绍 1.1 认识防抖节流函数 1.2 认识防抖函数 1.3 防抖函数应用 1.4 认识节流函数 1.5 节流函数应用 1.6 生活中的例子 2.Underscore库 2. ...

  9. python主函数入口_Python 入口函数(菜鸟入门)

    Python 入口函数(菜鸟入门) 最近在组内研究专项项目,其中的一个现有工具是用 Python 开发的,我的目标是对这款工具的流程进行优化.虽然可以找到对应的开发者了解现有流程,然后结合我的研究提出 ...

  10. python主函数入口_python类 + mian()函数

    main函数 import sklearn import numpy as np print(sklearn) # print("hello") ra = np.random.ra ...

最新文章

  1. eclipse配置struts.xml自动提示
  2. 【ROM修改教程】添加高级电源重启菜单(安卓4.0.4官方ROM)
  3. javascript箭头函数和this的指向问题
  4. 活动延期通知 | 7.31 阿里云 Serverless Developer Meetup 杭州站本周六见!
  5. PHP-RSA加密跨域通讯实战
  6. 网站搭建从零开始(三)域名解析
  7. Linux获取本机hostname函数,Linux下获得主机与域名-gethostbyname和gethostbyaddr
  8. 真格量化——50etf与期权对冲策略
  9. Problem E: 校庆
  10. stringbuffer判断是否为空
  11. 番茄时间管理法(Pomodoro Technique)
  12. linux服务器离线安装python第三方库
  13. 数据库锁,事务特性,脏读,幻读,不可重复度,隔离级别,分布式事务,本地事务的介绍
  14. oracle18c创建数据库,Oracle 18C 手工创建CDB
  15. css中relative、absolute和float
  16. 天河二号上运行ZHT(a zero-hop distributed table)
  17. 408复习经验先写到这,后面再补充
  18. 软件测试人员分工【管理层必看】
  19. pdf文件过大如何缩小上传
  20. 用串口(TFTP)给设备升级程序

热门文章

  1. python爬虫系统知识_网络爬虫基础知识(Python实现)
  2. python正则匹配_Python中的正则表达式(re)
  3. php 变量 unset,在PHP中unset变量
  4. 一句话菜刀 php eval,如何基于菜刀PHP一句话实现单个文件批量上传?
  5. java public就是可选吗_java 中的public
  6. python仿真电力系统自动化技术_基于MSAA的自动化封装和设计—python版(转)
  7. 查看mysql下的内容
  8. Angr安装与使用之使用篇(一)
  9. 23.3.3 Web存储机制【JavaScript高级程序设计第三版】
  10. 阿里大于短信返回XML