VS2010 & DirectX11 SDK & Windows SDK 编程过程中的 错误/异常/解决方案 记录 【二】

静态库、预编译头 问题

问题描述:先创建了一个静态库, 编码编译完成后, 创建新的测试用项目 main_test, 

#include “我的库的声明头文件”
...
#pragma comment( lib, "我的库名.lib");

但是编译 main_test 时出现 :

错误    42    error LNK2019: 无法解析的外部符号 "public: bool __thiscall _evl::EMinHeap<class TimerNode>::IsEmpty(void)const " (?IsEmpty@?$EMinHeap@VTimerNode@@@_evl@@QBE_NXZ),该符号在函数 "public: virtual void __thiscall TimerMinHeap::Run(void)" (?Run@TimerMinHeap@@UAEXXZ) 中被引用    E:\workstation\vs2010\evllib.src.20130201.5\main_test\timer.obj    main_test

这一类连接错误, 说明在生成编译生成静态库lib 时, 某些 cpp源没有最终生成 obj 到 lib内, 导致无法找到相应的符号(无法解析的外部符号);

问题定位到 静态库 的生成过程中, 发现有

warning LNK4221: 此对象文件未定义任何之前未定义的公共符号,因此任何耗用此库的链接操作都不会使用此文件

对应英文的意思是 :

warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library

msdn的说法是 obj文件的 链接顺序问题, 需要设置 /Yu /Yc 及 预编译头 : 

Linker warning LNK4221, and some tips to avoid it
http://blogs.msdn.com/b/vcblog/archive/2009/07/21/linker-warning-lnk4221-and-some-tips-to-avoid-it.aspx

摘取部分如下:

Typical user scenarios

In practice, most LNK4221 warnings occur on stdafx.obj, which is the name of the precompiled header. In this section, we will focus on two typical “real-world” scenarios and provide corresponding workarounds.

Build a static library with object files

Generally, LNK4221 should not be thrown on stdafx.obj. But in some cases, such as migrating from other IDEs or project systems, there are more than one source files which are specified with /Yc, hence the .obj files of them will all contain the content from stdafx.obj, if any of them is processed prior to stdafx.obj, a LNK4221 will be thrown. If this occurs, try following steps to check your configuration of Precompiled Headers.

1. In the Property Dialog of the project, select “Configuration Properties”->”C/C++”->”Precompiled Headers”. Select “Use Precompiled Header (/Yu)” for “Create/Use Precompiled Header”, and accept the default values for the other two options.

 

2. Right click “stdafx.cpp” in solution explorer. Select “Properties”, then select “Configuration Properties” -> ”C/C++” -> “Precompiled Headers”. Select “Create Precompiled Header (/Yc)” for “Create/Use Precompiled Header”, and accept the default values for other two options.

 

3. Save the changes and rebuild the project. If the problem remains, check the build log to confirm that only one source file (“stdafx.cpp” here) is compiled with /Yc and the others are compiled with /Yu.

 

 但是当我完成后, 编译器对每个 cpp 文件出现如下问题:

fatal error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "StdAfx.h"”?

Did you forget to add'#include"stdafx.h"'to your source?

这是因为 整个项目都是默认设置使用 stdafx.h 所以 每个 cpp文件里也必须有 

#include "StdAfx.h"
这怎么行呢, 这个静态库的 源文件是 打算用作跨平台的, 将来还要在 g++ 上编译生成 .a 文件; 解决方式是 对每个 cpp 文件的属性设置成 “不使用预编译头”。 学习自
http://blog.sina.com.cn/s/blog_58649eb30100th2k.html。
  • fatal error C1004 : 发现意外的文件尾

使用 条件宏 不正确:

#if MACRO_ONE
    ...

#if MACRO_TWO
    ...

#elif MACRO_THREE
    ...

#endif
#if MACRO_TWO 应该改为
#elif MACRO_TWO


  • 对于有 非VOID 返回值的函数, 某个分支没有 显示返回值 的 警告修改为错误:


#pragram warning( error : 4715)


  • PostQueuedCompletionStatus 发送自定义 事件 触发 GetQueuedCompletionStatus 的问题解决记录 

首先 这两个函数 有这样的对应关系:
BOOL WINAPI GetQueuedCompletionStatus(
  _In_   HANDLE CompletionPort,
  _Out_  LPDWORD lpNumberOfBytes,
  _Out_  PULONG_PTR lpCompletionKey,
  _Out_  LPOVERLAPPED *lpOverlapped,
  _In_   DWORD dwMilliseconds
);

BOOL WINAPI PostQueuedCompletionStatus(
  _In_      HANDLE CompletionPort,
  _In_      DWORD dwNumberOfBytesTransferred,
  _In_      ULONG_PTR dwCompletionKey,
  _In_opt_  LPOVERLAPPED lpOverlapped
);
 
 
CompletionPort [in]
A handle to an I/O completion port to which the I/O completion packet is to be posted.

dwNumberOfBytesTransferred [in]
The value to be returned through the lpNumberOfBytesTransferredparameter of the GetQueuedCompletionStatus function.

dwCompletionKey [in]
The value to be returned through the lpCompletionKey parameter of theGetQueuedCompletionStatus function.

lpOverlapped [in, optional]
The value to be returned through the lpOverlapped parameter of theGetQueuedCompletionStatus function.
 

此间主要有两个问题没有理清楚:

1.没有想明白 第三个参数 _In_  ULONG_PTR dwCompletionKey, 可以是自定义的数据类型, 例如int, 我的工程中传值为 iocp_api::Accept(=2), 即简单的 int 数值 值为 2, 那么在

BOOL WINAPI GetQueuedCompletionStatus(
  _In_   HANDLE CompletionPort,
  _Out_  LPDWORD lpNumberOfBytes,
  _Out_  PULONG_PTR lpCompletionKey,
  _Out_  LPOVERLAPPED *lpOverlapped,
  _In_   DWORD dwMilliseconds
);
函数 的 _Out_  PULONG_PTR lpCompletionKey 的值就会是 2, 我的问题出在“进行普通的 GetQueuedCompletionStatus() 处理时, 参数是返回地址指针类型“ , 没有意识到 该指针的值 就是 0x00000002

2.没有注意到 两个函数的 微妙非堆成区别:
BOOL WINAPI GetQueuedCompletionStatus( ...,  _Out_  LPOVERLAPPED *lpOverlapped, ... );
BOOL WINAPI PostQueuedCompletionStatus( ...,  _In_opt_  LPOVERLAPPED lpOverlapped );
GetQueuedCompletionStatus() 要求的是 LPOVERLAPPED * 
而 PostQueuedCompletionStatus() 是 LPOVERLAPPED

转载于:https://www.cnblogs.com/Wilson-Loo/archive/2013/06/06/2889983.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值