重粒子的运行轨迹

Compiling ...
baryon.cpp
baryon.cpp(1) : warning C0000: all glory is fleeing
F1:Technology is worthless - even dangerous - if we don't pay attention to the human aspects of both its use and its construction
随笔 - 58, 评论 - 276, 引用 - 0

导航

关于

标签

每月存档

最新留言

  • re: C#3.0

    by 好(匿名) on 2004/10/27 19:39:00
  • re: C#3.0
    超前
    by 超前(匿名) on 2004/10/27 19:38:00
  • re: 动机与价值
    发起人,写的很好
    by 支持(匿名) on 2004/10/27 19:34:00
  • re: 动机与价值
    免费是一种运营模式,嫌钱才是目的,世界上的free是相对的!
    by 波(匿名) on 2004/10/27 19:32:00
  • re: QA
    コンポボックスですかな?わからない。宅急便さんが着たら、相談してもいいよ。
    by 重粒子(匿名) on 2004/10/22 14:58:00
  • re: QA
    連絡するとき、相手は午前中は難しいと言ってた。あとは、いくといわれました。 <br>そして自転車のコンポも必要です。コンポはどう意味ですか。聞いてもわからないです。
    by leptonw(匿名) on 2004/10/22 14:42:00
  • re: QA
    まあ、連絡したね。大丈夫はず。
    by 重粒子(匿名) on 2004/10/22 14:33:00
  • re: QA
    宅急便がもし明日、来られなかったら、困ります。
    by leptonw (匿名) on 2004/10/22 13:54:00
  • re: QA
    送り状については明日、宅急便さんが着たら、書きます
    by 重粒子(匿名) on 2004/10/22 13:29:00
  • re: QA
    削除します
    by 重粒子(匿名) on 2004/10/22 13:27:00
  • re: QA
    借りたときには言ったことがありますよ。
    by 重粒子(匿名) on 2004/10/22 13:27:00
  • re: QA
    bedの件はhuang yanにお知らせしたほうがいいですが。
    by leptonw(匿名) on 2004/10/22 13:14:00
  • re: QA
    メールとか削除しますか?
    by leptonw (匿名) on 2004/10/22 13:06:00
  • re: QA
    先ほど宅急便に連絡時、送り状とか言わなかったですが。
    by leptonw (匿名) on 2004/10/22 13:05:00
  • re: QA
    OK
    by 重粒子(匿名) on 2004/10/22 12:07:00
  • re: QA
    >吉原さんは本社と確認するって言われましたね <br>言いました。また「私から王さんに連絡します。」と言いました。でも今までまだ。私は電話するのがちょっと嫌ですから。
    by leptonw(匿名) on 2004/10/22 11:59:00
  • re: QA
    自転車は処理しませんよ。宅急便に頼みました。
    by leptonw(匿名) on 2004/10/22 11:57:00
  • re: QA
    OK。bedをごみとして処理しますね。どう2階から1階に移動するの? <br>
    by 重粒子(匿名) on 2004/10/22 11:50:00
  • re: QA
    処理します。自転車も?
    by 重粒子(匿名) on 2004/10/22 11:49:00
  • re: QA
    宅急便に頼みました。明日午前中来られますといわれました。 <br>私は自転車より大きな荷物はないと言いましたので。
    by leptonw(匿名) on 2004/10/22 11:47:00
  • re: QA
    粗大ゴミとして処理すれば、一個810円です。処理しますか?
    by leptonw(匿名) on 2004/10/22 11:45:00
  • re: QA
    困る。だめなら、値段無視してね
    by 重粒子(匿名) on 2004/10/22 10:56:00
  • re: QA
    引越しセンターでは自転車は一台、1万円以上かかるそうです。
    by leptonw(匿名) on 2004/10/22 10:49:00
  • re: QA
    だめなら、10000円引越しもあるんです。でも、電話番号わかりません。WEBだけ知ってる。 <br>メールの最後をご覧ください
    by 重粒子(匿名) on 2004/10/22 10:48:00
  • re: QA
    自転車とベッドがちょっと預かりにくいです。どうしましょうか
    by leptonw(匿名) on 2004/10/22 10:46:00

广告

C++的Tips,无兴趣勿看之一

1,左值,右值

我们知道对一个变量付值可以这么写

   i = 7;            // Correct. A variable name, i, is an l-value.

   //7 = i;            // C2106. A constant, 7, is an r-value.
是不对的。

也许你并不知道可以这么用

    ((i < 3) ? i : j) = 8; // Correct. Conditional operator (? :)
                          //  returns an l-value.
根据 i 的初始值不同,8要么付给 i ,要么付给 j

2,2的幂

我们知道C++里求一个数的幂可以这么做

double x = 2.0, y = 3.0, z;

 z = pow( x, y );
也许你不知道如果是求2的整数次方的话有更简单的方法

int y=3,z;

z=1<<y; //相当于(int)pow(2.0, y);

当然你要注意结果不要溢出。

3,使用移位来求一个整数的乘2的倍数,除2的倍数

这个Tip可以说很多教科书里都写了,我就不重复了。

 

posted on 2004-08-10 17:47:00 by baryon  评论(2) 阅读(809)

揭开native event的面纱

这是我的第3篇关与native event的随笔。第一篇对native event作了简介。第二篇报告一个BUG。这一篇我们看看native event是如何实现的,并且尝试解决我们遇到的BUG。

从VC7(Microsoft Visual C++ .NET (2002) )开始MSVC提供了native event这一机制,试图为C++引入一个实现delegate的办法。一共提供了4个扩展关键子:__event (定义一个event),__raise(触发一个event),__hook(将一个成员函数连到event上),__unhook(去掉指定的函数),和两个作用在类上的特性:event_source(一个事件源),event_receiver(一个事件接受者)。

为什么会提供这么多看上去很丑陋的关键子呢?这些关键子生成了什么样的代码呢?

可以使用下面的编译命令来编译我在第二篇随笔里的代码。

cl /Fx /Fas native_event.cpp

/Fx编译选项会生成一个native_event.mrg.cpp,这是MSVC编译器对特性作了展开以后生成的源代码。/Fas编译选项生成相应的汇编代码。

我们看看native_event.mrg.cpp就足够了解native event的实现方法了。

__event关键子被展开成为一个事件函数链表指针,一个虚构造体,一个模板构造体,3个模板函数,一个名为__RemoveAllEventHandlers的成员函数,一个与event名同名的inline函数。除此以外还有4个辅助结构体。 可见event机制是非常类似宏定义的实现方案

__hook通过__AddEventHandler模板函数将函数指针追加到函数链表里。__unhook从链表中删除函数指针。

__raise本身没有什么用处。实际调用的事件函数的时候,会循环调用函数链表里的函数。函数链表的每个节点里都存储了对象实体指针(this)和成员函数指针。成员函数指针同void*指针的转换利用了__eventingGetAddr这个灵巧的辅助类。

虽然代码看上去有点乱,但并不是很长,应该很容易看懂。

我在第二篇随笔里提到的bug,发生在

??????? int __isEqual(void* p, void* pfn)
??????? {
??????????? return ((T*) p == this->p) && (__eventingGetAddr::__getMAddr(pfn) == (void ( T::*) ()) pmfn);
??????? }
这个函数里。多继承的情况下对(void ( T::*) ()) 形式的指针做比较是比较微妙的,明明相等的指针确返回了false。查看汇编代码发现一共比较了8个byte,两个DWORD PTR,具体为什么这么做我还需要做一些分析。

看上去一个可行的代替方案是:

??????? int __isEqual(void* p, void* pfn)
??????? {
??????????? return ((T*) p == this->p) && pfn == __eventingGetAddr::__getVAddr((void (T::*) ()) pmfn));
??????? }
将函数指针转换成void*,然后再做比较。从asm看到这产生了高效的代码。

这个BUG导致的后果就是:无法在ATL/WTL中使用native event。这使的这一机制几乎失去了意义。

警告:使用native event要小心。

建议:在MSVC改正BUG之前不要使用native event。

CodeProject里有一篇最近发表的文章提出一种FastDelegate方法,似乎是不错的single-target delegate 解决方案。boost的function和signals则是更加值得关注的。

posted on 2004-07-07 14:49:00 by baryon  评论(1) 阅读(877)

BUG Report: Failed When a Native Event is Unhooked with with Multi-Heritance

SYMPTOMS

当在一个使用多继承类作为event_receiver的未托管应用程序中unhook (__unhook) 一个native events时, 将会失败。__unhook将返回1(表明没有成功地unhook。在应用程序结束以后native event机制造成了内存泄漏.

CAUSE

这个问题发生在事件的接受者(event_receiver)是多继承类的情况下。在unhook的时候event的注入代码无法正确比较成员函数指针。

WORKAROUND

这个问题可以使用下面的代码重现:

#include

class A
{
?int a;
};

class B
{
?int b;
};

[event_source(native)]
class CSource
{
public:
?? __event void MyEvent(int nValue);
};

[event_receiver(native)]
class CReceiver : public A, public B //多继承
{
public:
?? void MyHandler1(int nValue) {
????? printf("MyHandler1 was called with value %d.\n", nValue);
?? }

?? void MyHandler2(int nValue) {
????? printf("MyHandler2 was called with value %d.\n", nValue);
?? }
};

int main() {
?? CSource source;
?? CReceiver receiver;

?? __unhook(&CSource::MyEvent, &source, &CReceiver::MyHandler2, &receiver);
?? __hook(&CSource::MyEvent, &source, &CReceiver::MyHandler1, &receiver);
?? __raise source.MyEvent(1);
?? __unhook(&CSource::MyEvent, &source, &CReceiver::MyHandler1, &receiver);//失败
?? __hook(&CSource::MyEvent, &source, &CReceiver::MyHandler2, &receiver);
?? __raise source.MyEvent(2);
?? __unhook(&CSource::MyEvent, &source, &CReceiver::MyHandler2, &receiver);//失败
?
}

运行结果

MyHandler1 was called with value 1.
MyHandler2 was called with value 2.
MyHandler1 was called with value 2.

MyHandler2没有被正确unhook。

The information in this article applies to:

  • Microsoft Visual C++ .NET (2002)
  • Microsoft Visual C++ .NET (2003)
  • Visual C++ 2005 Express Edition Beta

posted on 2004-07-07 11:10:00 by baryon  评论(0) 阅读(798)

native event简介

几乎是在不知不觉中VC7为C++提供了native event这一扩展功能。

背景和动机:
当一个对象改变了状态,他怎么通知"关心"它的其他对象呢?
C++一直没有一个很好的机制解决这个问题。一般的作法是采用从C语言继承过来的回调函数的办法。
函数指针的定义方法
int func(int a,int b,int c);
int (*fp)(int ,int ,int) ;//fp是一个函数指针,
fp=func;

这种回调机制有几个问题
1,一个回调函数只能通知一个接受对象,无法同时通知多个接受者
2,如果没有接受对象需要单独判断
3,使用类函数做回调函数会比较麻烦,一般使用静态函数

boost::function是一套对回调函数的封装类。多少缓解了上面的几个问题。

如果是windows编程的话,可以利用另外一些机制完成这种对象之间的"通知"任务。比如消息,EventObject。但这些方式都依赖与复杂的SDK API。不是C++语言本身的功能。

总之C++其实没有一个属于自己的事件模型。

模型:
从VC7开始,MS提供了一个扩展的C++事件模型:Unified Event Model。 这个模型统一提供了一致的方法来解决在native C++(非COM) , COM, 和managed classes中的事件通知需求。

适用:
这种模型支持对象之间事件通知。支持多线城并发。支持从拥有事件类继承,也支持子类里拥有事件定义。

例子:
MSDN上提供了基本native event的例子。网址为:
http://msdn.microsoft.com/library/en-us/vccore/html/vcconEventHandlingInNativeC.asp

分析:
我们通过一个小程序看一下,native event的内部机制。这个小程序和分析结论来自http://lamoo.s53.xrea.com/diary/diary2003a.html
我对其做个小的修改。(见附件)

1,一个event占用4bytes的内存。
2,分配内存的时候一个类里定义的event会集中在类的最后集中分配。
3,按照追加(hook)事件的顺序,内存中维持一个单向链表。
4,hook事件的接受对象如果被删除(delete),不会自动被unhook。如果没有明确地unhook,下一次raise事件是,会有不可预料的错误。
5,event_source和event_receiver属性可以省略。


实做:
我在自己的一个程序中使用了native event,那是一个通过HTTP协议自动下载更新模块的类。那个类实例运行在单独的线城里,通过event将联接网络,下载的进度通知父线城,父线城是一个对话框,将收到的信息显示出来。这一切类似IE的下载对话框。也就是说事件是垮线城通知的。
如果你熟悉ATL7,那里面有一个CAtlHttpClient类,它的通知方式采用的是回调函数。而通常的作法往往是SendMessage给一个父线城的窗口句柄,通过windows的消息循环调用显示状态的函数。

课题:
我们现在面对两个问题:
1,一个hook必须对应一个unhook,这就像分配内存是一个new必须对应一个delete一样。如果忘记unhook就会发生内存泄漏。
2,任何一个接受者对象被delete以后,不会自动unhook。
所以我们有一个课题,就是对这种事件模型进行包装,制作一个包装类(wrapper class)来解决上面这两个问题。这个类应该类似auto_ptr,利用析构机制自动unhook,还要像boost::function一样支持各种各样的event函数。


参考
1,http://msdn.microsoft.com/library/en-us/vccore/html/vcconEventHandlingInNativeC.asp
2,http://lamoo.s53.xrea.com/diary/diary2003a.html
3,http://www.boost.org/doc/html/function.html

posted on 2004-03-30 16:28:00 by baryon  评论(3) 阅读(1261)

Powered by: Joycode.MVC引擎 0.5.2.0