2008-10-25

as 和 强制转换

 
此邮件可以和下列文件或链接附件一起发送了。
as.JPG

说明: 为了保护计算机不受病毒的侵害,电子邮件程序会阻止发送或接收某些文件附件的类型。请检查电子邮件设置是如何处理附件的。

Convert.ToInt32(null)会返回0而不会产生任何异常,但int.Parse(null)则会产生异常。

        try
        {
            int.Parse(null);
        }
        catch(Exception ex)
        {
            Response.Write(ex.Message);
        }

        try
        {
            int.Parse("mxmdslsl");
        }
        catch (Exception ex)
        {
            Response.Write(ex.Message);
        }

        int i = -1;

        try
        {
            i = Convert.ToInt32(null);
        }
        catch (Exception ex)
        {
            Response.Write(ex.Message);
        }

        Response.Write(i);

输出:

Value cannot be null. Parameter name: String
Input string was not in a correct format.
0

2008-10-16

阅读effective C++时未解决的问题,做个标记,有空再调查



1.在创建资源需要申请内存时,是否需要捕获内存不足时的异常。

2.为了减少代码的冗余,在拷贝构造函数中调用赋值运算符或者在赋值运算符中调用拷贝构造函数带来的后果是什么。



今天的口号是:还我清白.

不要析构函数中抛出异常

Effective C++ 第3版45页第5行告诉我们:
不要析构函数中抛出异常, 因为C++中同时出现两个异常意味着不确定行为.
大家可以运行下面这段程序看一下结果.

#include "stdafx.h"
#include
#include
using namespace std;

class A
{
public:
~A()
{
cout << "~A()" << endl;
throw 3;
}
};

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

try
{
A a;
A a2;

}
catch(...)
{
cout << "exception catched" << endl;
}

return 0;
}

另外作者为我们提供了一些对策来处理析构中的异常.详情参见effective c++ 第3版45页

2008-10-14

c++两点: 1用拷贝赋值运算符调用拷贝构造函数. 2.构造函数互相调用


class A
{
public:
A(int _x)
{
new(this)A(_x, 23);     //调用另外一个构造函数
}

A(int _x, int _y) { x = _x; y = _y; }

public:
int x;
int y;
};

class B
{
public:
B() { x = 4; }

B(const B& rhs)
{
if ( this == &rhs ) return;
x = rhs.x;
}

B& operator= (const B& rhs)
{
this->B::B(rhs); // 调用拷贝构造函数
}
public:
int x;
};

int _tmain(int argc, _TCHAR* argv[])
{
A a(3);

B b;
B b2(b);

cout << a.x << " " << a.y << endl;
cout << b2.x ;
return 0;
}

2008-10-12

软件推荐: Microsoft Office OneNote

Microsoft Office OneNote 是一个专门用于做笔记和搜集、整理资料的一个强大的应用程序。
利用它可 在上课时记下教授的讲课内容,开会时做会议记录,甚至只是写一个待办事宜列表;搜集资料时很方便地进行资料分类管理、检索;特别是不需要额外地进行保存,完全由程序自动保存。
没有用过的朋友可以试一下这个软件。

另外可以和outlook合作使用
如果有tabletPC就更方便啦, 手写记录的内容也是可被搜索的.

python 中动态执行 JavaScript代码



this post is obviously out of date, so now you should try  https://code.google.com/p/pyv8/  
这个帖子已经明显过时了,你应该试试https://code.google.com/p/pyv8/



-------------------------
以前因为写了这段代码, 刷了一下google adsense的链接, 结果google不让我用adsense了.
因为google adsense中javascript代码应该是通过混淆的,当时分析没有找到头绪,就找到了spidermonkey.
这段代码主要是在python中通过spidermonkey类库, 动态执行混淆后的javascript,找到真正链接.





a.py




from spidermonkey import Runtime
import time, urllib2, httplib, random, re
import urllister

def get():
    httplib.HTTPConnection.debuglevel = 1

baseurl = 'http://pagead2.googlesyndication.com'
dt = str(int(time.time() * 1000))
print 'start sleep...'
time.sleep(random.randint(0, 9))
print dt, 'end sleep...'
url = 'http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-6581680843370427&dt=' + dt + '&lmt=1156579898&format=468x60_as&output=html&url=http%3A%2F%2Flocalhost%2Ftest.html&color_bg=F6F6F6&color_text=9E5205&color_link=B8A80D&color_url=B8A80D&color_border=9E5205&ad_type=text&cc=100&u_h=800&u_w=1280&u_ah=779&u_aw=1280&u_cd=24&u_tz=480&u_his=1&u_java=true&u_nplug=9&u_nmime=91'

request = urllib2.Request(url)
request.add_header('USer-Agent',
                   'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.5) Gecko/20060731 Ubuntu/dapper-security Firefox/1.5.0.5')
opener = urllib2.build_opener()
conn = opener.open(request)
html = conn.read()
conn.close()

print html
regex = re.compile(r'function jcc\(a\).*function ha\(a\).*?jcc\(a\).*?\}')
m = regex.search(html)
if m is not None:
    func = m.group(0)
func = re.sub(r'pha=document\.getElementById\(a\)', 'phahref=a', func)
print func
func = re.sub(r'pha\.href', 'phahref', func)
print func
func = re.sub(r"a=='aw0'", 'a == a', func)
print func
else:
    pass

parser = urllister.URLLister()

parser.feed(html)
parser.close()

href = baseurl + parser.href[0]

javascript = func + ' href="' + href + '"; ha(href); print (href);'
print javascript
rt = Runtime()
cx = rt.new_context()
f = cx.eval_script(javascript)
s = cx.get_global("phahref");
print s

request = urllib2.Request(s)
request.add_header('USer-Agent',
                   'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.5) Gecko/20060731 Ubuntu/dapper-security Firefox/1.5.0.5')
opener = urllib2.build_opener()
conn = opener.open(request)
html = conn.read()
conn.close()

if __name__ == '__main__':
    import thread
    import analy

    for i in range(20):
        print get
        thread.start_new_thread(analy.get, ())
        print i

-->


参考网址:

http://wwwsearch.sourceforge.net/python-spidermonkey/
http://pypi.python.org/pypi/python-spidermonkey/0.0.1a

Effective C++ 第七条款中讲到: 多态基类声明virtual析构函数

Effective C++ 第七条款中讲到: 多态基类声明virtual析构函数

 

关于这个问题, 我们有一个疑问:

如果父类中不定义虚的析构函数, 而通过父类的指针delete子类的对象, 会怎么样?

 

class Base

{

private:

      int m_iBaseData;

};

 

class Derived : public Base

{

public:

      Derived()    {          m_piDerivedData = new int(3);    }

      ~Derived()  {          delete m_piDerivedData;           }

private:

      int * m_piDerivedData;

};

 

int _tmain(int argc, _TCHAR* argv[])

{

      Base BaseObj;

      Base* pb =  new Derived();

      delete pb;

 

      return 0;

}

 

我觉得这个问题应该分两块来剖析.

1.       C++语法方面,

因为父类没有声明虚函数,所以不会有虚表出现(参见C++对象模型第一章), 进而无法实现多态, 所以子类的析构函数不会被调用到.

有一点我们可以肯定, 因为子类的析构函数没有被调用到, 子类申请的资源将不能通过析构函数释放, 将造成内存泄露.

2.       从内存管理方面

首先, 我们知道CRT进行内存管理过程中, new一块内存时需要提供一个size, 这样delete时才能记住, 先前申请了多大的内存块.参考下面一段话:

 

摘自: http://topic.csdn.net/t/20061104/21/5133631.html

这里有一个问题,就是当我们调用   new   operator   分配内存时,有一个   size   参数表明需要分配多大的内存。但是当调用   delete   operator   时,却没有类似的参数,那么   delete   operator   如何能够知道需要释放该指针指向的内存块的大小呢?答案是:对于系统自有的数据类型,语言本身就能区分内存块的大小,而对于自定义数据类型(如我们自定义的类),则   operator   new     operator   delete   之间需要互相传递信息。   
    
 
  当我们使用   operator   new   为一个自定义类型对象分配内存时,实际上我们得到的内存要比实际对象的内存大一些,这些内存除了要存储对象数据外,还需要记录这片内存的大小,此方法称为   cookie.这一点上的实现依据不同的编译器不同。(例如   MFC   选择在所分配内存的头部存储对象实际数据,而后面的部分存储边界标志和内存大小信息。g++   则采用在所分配内存的头   4   个自己存储相关信息,而后面的内存存储对象实际数据。)当我们使用   delete   operator   进行内存释放操作时,delete   operator   就可以根据这些信息正确的释放指针所指向的内存块。   
    
 
  以上论述的是对于单个对象的内存分配/释放,当我们为数组分配/释放内存时,虽然我们仍然使用   new   operator     delete   operator,但是其内部行为却有不同:new   operator   调用了operator   new   的数组版的兄弟-   operator   new[],而后针对每一个数组成员调用构造函数。而   delete   operator   先对每一个数组成员调用析构函数,而后调用   operator   delete[]   来释放内存。需要注意的是,当我们创建或释放由自定义数据类型所构成的数组时,编译器为了能够标识出在   operator   delete[]   中所需释放的内存块的大小,也使用了编译器相关的   cookie   技术。

 

我们来做一个实验:

#include "stdafx.h"

#include <iostream>

using namespace std;

 

class Base

{

public:

   Base() { m_iX = 2; m_iY = 3; }

private:

   int m_iX;

   int m_iY;

};

 

int _tmain(int argc, _TCHAR* argv[])

{

   Base* pb =  new Base();

   int * int_pointer_to_base = (int*) pb; //Base类的指针转成int*

 

   delete int_pointer_to_base;

   return 0;

}

   设置断点: 在执行delete int_pointer_to_base;之前, 内存状况如图1所示:

从图中看到int_pointer_to_base实际上是指向了m_iX的位置.

F10再走一步, 当执行完delete 操作后, 内存如下图2所示:

我们看到delete, m_iX, m_iY内存变成了0xfeeefeee(Debug模式下, VC编译器自动将delete掉的内存块, 填充上0xfeee), 虽然Release模式下, m_iXm_iY的内存不会被填充0xfeee, 但是我们已经知道, 内存管理中已经将申请时的大小sizeof(Base)回收了.

 

结论:

    Base BaseObj;

      Base* pb =  new Derived();

      delete pb;

 

通过父类指针来deletenew出来的子类的对象, 对于子类对象的内存区域中(继承中子类实例内存部局, 请参考C++对象模型), 不仅父类的部分会被回收, 子类的部分也会被回收.

 



图1:
图2:

2008-10-11

繁忙一周

这周真是忙, 每天都11:30以后睡觉, 7点起床, 白天喝咖啡.

今天是周六, 早上一起睡到12:00才起床, 真是睡到自然醒 :)




顺便推荐一个很不错的网站, 提供相片打印服务(新注册会员还有20张免费打印优惠), 把你的数码照片通过这个
网站打印,并邮寄出去.

http://www.kachayu.com

2008-10-06

国庆总结

国庆就背日语来着, 背了大概18课的单词及语法.

另外把越狱第一季从头到尾又看了一遍. 这些编剧太强了.