首页
社区
课程
招聘
[求助]驱动中可以写构造函数吗
发表于: 2012-10-24 11:15 7593

[求助]驱动中可以写构造函数吗

2012-10-24 11:15
7593
我在写驱动的时候用到了C++类,并且写了构造函数,但是只要带上构造函数就编译出错:
warning treated as error; no output file generated       

但如果把构造函数删除,就编译通过,这是为什么?难道驱动中不能写构造函数吗?

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (11)
雪    币: 1054
活跃值: (1258)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
驱动 是 c
2012-10-24 11:58
0
雪    币: 101
活跃值: (82)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
驱动中是可以用C++写的,只需要加上c编译方式就可以了

#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <NTDDK.h> //这里包含需要用C方式编译的头文件
#ifdef __cplusplus
}
#endif
2012-10-24 12:15
0
雪    币: 14
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不是你加入了构造函数出错,是存在.CRT节数据未初始化。
当你有构造函数时,或者有全局变量需要计算的时,编译器会生成一个Stub函数处理初始化,并把函数指针放到.CRT初始化列表中,会有一个LNK4210 warning,所以会提示错误。
解决方法,在source里面加入LINK_LIB_IGNORE=4210就可以了,不过这样的话,构造函数还是没有被执行。要执行必须添加一些代码。
#ifndef cppsupport_HPP
#define cppsupport_HPP
//*************************************************************************
#include "new.hpp"
//*************************************************************************
typedef void (__cdecl *PFN_T)();
//*************************************************************************
class AtExitCall
{
public:
	AtExitCall(PFN_T pF)
	{
		m_pF = pF;
		m_Next = m_ListHeader;
		m_ListHeader = this;
	}

	~AtExitCall(void)
	{
		m_pF();
		m_ListHeader = this->m_Next;
	}

	static void	Run()
	{
		while(m_ListHeader)
			delete m_ListHeader;
	}

	PFN_T	m_pF;
	AtExitCall* m_Next;
	static AtExitCall* m_ListHeader;
	static NTSTATUS m_Status;
};
//*************************************************************************
__declspec(selectany) AtExitCall* AtExitCall::m_ListHeader = NULL;
__declspec(selectany) NTSTATUS    AtExitCall::m_Status = STATUS_SUCCESS;
//*************************************************************************
#if _X86_
#pragma data_seg(".CRT$XCA")
__declspec(selectany) PFN_T	xc_a[1] = {0};
#pragma data_seg(".CRT$XCZ")
__declspec(selectany) PFN_T	xc_z[1] = {0};
#else
#pragma section(".CRT$XCA", long, read)
__declspec(allocate(".CRT$XCA")) __declspec(selectany) PFN_T xc_a[1] = {0};
#pragma section(".CRT$XCZ", long, read)
__declspec(allocate(".CRT$XCZ")) __declspec(selectany) PFN_T xc_z[1] = {0};
#endif
#pragma data_seg()
#pragma comment(linker, "/merge:.CRT=.data")
//*************************************************************************
inline NTSTATUS cpplib_Startup()
{
	for(PFN_T *pF = xc_a;pF < xc_z;pF++)
		if(*pF)
			(*pF)();

	return AtExitCall::m_Status;
}
//*************************************************************************
inline void cpplib_Exit()
{
	AtExitCall::Run();
}
//*************************************************************************
extern "C" inline int __cdecl atexit(PFN_T pF)
{
	return (new AtExitCall(pF) == 0) ? (*pF)(), AtExitCall::m_Status = STATUS_UNSUCCESSFUL, 1 : 0;
}
//*************************************************************************
extern "C" inline int _cdecl puts(const char *p)
{
	DbgPrint(p);
	return 0;
}
//*************************************************************************
extern "C" inline void _cdecl exit(int Code)
{
	KeBugCheck(Code);
}
//*************************************************************************
#endif

LINK_LIB_IGNORE=4210,4254
如果要用new创建类的话,自己再实现new和delete。
2012-10-24 14:46
0
雪    币: 28
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我想问下啊,这些你是看《编译原理》才懂的吗?
2012-10-24 14:59
0
雪    币: 14
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
跟编译原理一毛钱关系都没有的(编译原理一直想认真看看,就是看不下去
看看vc目录下面的CRT源码加上IDA看看就知道了。(其实我是看Driver Works的)
驱动用C++尽量写完后用IDA看一遍,看看他添加了什么,优化了什么,妥当点。。
2012-10-24 15:26
0
雪    币: 209
活跃值: (808)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
使用C++编写内核模式驱动程序的缺点:

C++ 编译器执行的某些规则比标准 C 编译器更加严格,而且提供一些能够在驱动程序上下文中安全使用的附加特性。
正是一些“高级的”C++ 特性引起了内核模式代码中的问题,例如非 POD("plain old data",如 C++ 标准所定义)类和继承、模板和异常。这些问题主要是由 C++ 实现和内核环境引起,而不是 C++ 语言的内在属性。
内核模式中没有提供所有的标准库(C 或 C++)。
将 C++ 编译器用于内核模式代码,编译器生成的正确的目标代码未必是您期望的代码,其组织方式也未必是您所期望的。
C++ 比 C 更可能发生这种问题。您必须检查目标代码,以确保与您的期望一致,或者至少能在内核环境中正确工作。
目前可用的 C++ 编译器的输出不能保证在所有平台和版本的内核模式都能工作。代码使用的 C++“高级”特性越多,就越可能出现互操作性问题。
对于那些适合两种语言(C 和 C++)的区域,C++ 代码可能更容易出问题,因为 C++ 编译器做了更多的自动化工作,而且您可能不会意识到它导致了一个问题。 C++ 中更严格的类型检查可能不允许技术上合法但是语义上错误的构造。
涉及类层次结构或模板、异常,或各种形式的动态类型的任何内容都可能不安全。使用这些构造需要对生成的目标代码进行非常仔细的分析。
要使用 C++ 编写驱动程序,必须理解编译器生成的代码,确保目标代码满足内核模式要求,并确保其不会出现本文讨论的问题。
开发人员应该做好阅读目标代码、浏览链接图的准备,以确保数据和代码都位于合适的位置并且仅使用了内核安全的库。检查代码的可分页性、内联函数和正确的程序顺序。
使用 C++ 编写内核模式驱动程序面临的最严重的问题是内存页面的管理,尤其是内存中的代码,而不是数据。
C++ 编译器为非 POD 类和模板生成代码的方式使得很难确定执行一个函数所需的所有代码的去向,因此很难将代码安全地分页。
C++ 编译器没有提供机制来直接控制这些实体在内存中的位置。C++ 的设计并没有考虑控制内存位置的必要性。
C++ 函数的导出基于它们的完整签名,而不是(像 C 函数那样)只基于其名称。因此,无法将 C++ 函数可靠地导出到不同版本的库中,但是可以表示为 extern "C" 的 C++ 函数能够做到。
不是所有的库函数都可以在内核模式下使用,尤其是与“高级” C++ 语言特性相关的函数。
C++ 静态变量(在全局或局部范围内声明)为驱动程序带来了许多问题。
C++ 标准没有指定全局对象的初始化顺序,所以即使存在一种调用全局对象构造函数的机制,初始化顺序也必须由驱动程序明确地控制,或者该顺序无关紧要。

Microsoft 既不认可也不反对使用 C++ 编写内核模式驱动程序。这种保守态度一部分源于本文所述问题,也有一部分源于支持所有平台的需要。在尝试使用 C++ 进行任何内核模式开发之前,您必须清楚本文讲述的已知问题和风险,也应该警惕其他的未知问题。
2012-10-24 15:54
0
雪    币: 28
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不要粘贴党,好吗
2012-10-24 17:26
0
雪    币: 340
活跃值: (922)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
9
用class的话,要自己new出来,用好后再delete。
2012-10-25 09:35
0
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
10
没这个必要了

自己重载下new和delete就好了

然后不要有类似这样的声明就好了:

ClassA g_AObj;

需要用的地方,全部new
2012-10-25 15:39
0
雪    币: 405
活跃值: (2260)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
可以,貌似WIN8都在驱动中用C++的类了。
2012-10-26 11:45
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
12
WIN8 WDK开始与VS2012整合了,然后驱动开发本身全面可以OOP了~
但是你要是用老版本的DDK还是一样不推荐C++的OO特性
2012-10-26 12:01
0
游客
登录 | 注册 方可回帖
返回
//