POSIX规定的非线程安全函数列表

asctime ecvt gethostent getutxline putc_unlocked
basename encrypt getlogin gmtime putchar_unlocked
catgets endgrent getnetbyaddr hcreate putenv
crypt endpwent getnetbyname hdestroy pututxline
ctime endutxent getopt hsearch rand
dbm_clearerr fcvt getprotobyname inet_ntoa readdir
dbm_close ftw getprotobynumber L64a setenv
dbm_delete getcvt getprotobynumber lgamma setgrent
dbm_error getc_unlocked getprotoent lgammaf setkey
dbm_fetch getchar_unlocked getpwent lgammal setpwent
dbm_firstkey getdate getpwnam localeconv setutxent
dbm_nextkey getenv getpwuid lrand48 strerror
dbm_open getgrent getservbyname mrand48 strtok
dbm_store getgrgid getservbyport nftw ttyname
dirname getgrnam getservent nl_langinfo unsetenv
dlerror gethostbyaddr getutxent ptsname wcstombs
drand48 gethostbyname getutxid ptsname ectomb

是真的没时间么?

我一直给别人说、给自己说这几个月真的很忙!到底有多忙呢,一周加班3-4天很正常算忙么?

所以我给自己找了借口:现在很忙、抽不出时间,于是计划中的事情可以不做…做了80%的项目可以放到一边不顾。

但是,我却能有时间把2个WOW的账号从85练到90,还打了不少的副本。

关于打游戏,我给自己定下的一个自欺欺人规矩是:每天只打一个小时,但是我知道其实我远远的超过了这个时间…

今天依然加班,回家9点多,然后查了点资料。因为没玩游戏,突然间就思考了下最近这段时间,突然觉得有一丝的恐惧:

因为我发现最近这几个月我基本上没有进步,我没学到新的东西,已会的知识也没加深。更甚的是:一些知识因为一些时间没用,已经生疏了

看看书桌旁边的书架,满满的全是书,但是看完的又有几本呢?就算看了的,到现在又有几本还记得呢?

回忆下班回家后都做了些什么?

  • 开熊猫人之前,回家后大多时间在电脑上闲逛.仔细回忆了下,却又不知道闲逛了什么。
  • 开了熊猫人后,回家很多时间玩熊猫人去了.
  • 其他还做了什么?

下班后的时间就这么被浪费了!

再想想最近一段时间貌似也和各种新技术慢慢的走远了,自己也好像失去了一些原有的对技术激情。

这样是不对的!我需要改变

那么,看行动吧!

C, Cpp

不要总是将析构函数声明为Virtual (C++)

看到某个工程的代码,发现其中所有类的析构函数声明为虚函数.

我们知道,如果一个类作为另外一个类的基类,那么我们需要把此类的析构函数声明为虚函数,但是是不是所有的类的析构函数都声明为virtual最好呢?

首先,我们先来看看虚函数的实现机制其中和今天要说的主题相关性比较大的:

虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。 通过这张表来决定运行期间哪一个virtual函数将会被调用。

每一个带有virtual函数的类都有一个对应的Virtual Table。

因此,如果一个class中含有virtual函数,那么它的对象体积将会增加,并且这个对象也不在和其他语言(比如Fortran,比如C)的同样声明有着同样的结构,因为这些语言并没有vptr(virtual table pointer).

因此也就不能再把这个对象直接传递给其他语言所写的函数,移植性将会不再具有。(关于这点,其实我并没有体会,全是看书上说的 =。=,不过想想也是).

《Effective C++》上的建议是:只有当class含有至少一个virtual函数时候,才会他声明virtual析构函数

JSONKit Unable to Parse JSON With Single Quotes

一个项目中用到了JSONKit,一切都好好的,今天在做一个新的功能的时候,发现爆出了下面的错误

Error Domain=JKErrorDomain Code=-1 “Unexpected token, wanted ‘{‘, ‘}’, ‘[‘, ‘]’, ‘,’, ‘:’, ‘true’, ‘false’, ‘null’, ‘“STRING”’, ‘NUMBER’.” UserInfo=0x7c3de10 {JKAtIndexKey=22, JKLineNumberKey=1, NSLocalizedDescription=Unexpected token, wanted ‘{‘, ‘}’, ‘[‘, ‘]’, ‘,’, ‘:’, ‘true’, ‘false’, ‘null’, ‘“STRING”’, ‘NUMBER’.}

看到这个错误,首先想到的是给出的JSON字符串不正确,于是查看接口给出的JSON字符串

1
{"success":true,"msg":'操作成功'}

怎么看这个字符串都是一个正确的JSON字符串,为了验证,还把这个字符串复制到Safari的控制台和Firefox的Firebug中验证,都工作好好好的。

给出JSON的网页源代码中也没发现不可见字符,这下纠结了。

后来,仔细和以前接口返回的字符串对比,发现唯一不同的是以前使用的是双引号,这个接口使用的是单引号,会不会是这个原因?

修改JSON为:

1
{"success":true,"msg":"操作成功"}

果然一切OK了,看来JSONKit不支持单引号。这是JSONKit的问题么?

在JSONKit的这个Issue中找到了原因 https://github.com/johnezang/JSONKit/issues/75

去JSON的官网看了下,发现有下面这句话

A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.

原来双引号才是JSON的标准,单引号是不规范的,虽然我们平时用单引号很多时候都是工作正常的。

Supersequent Implementation

最近在做一个需要兼容多个iOS版本的App,写了很多的Category,因为有的iOS版本中不需要某些Category,于是就有了想在这个Category中调用原生方法的需求。

开始自己通过ObjC的runtime.h中提供的方法,尝试了一段时间无果后,在网上找到了这篇文章,发现里面其实就是我想要的:

http://cocoawithlove.com/2008/03/supersequent-implementation.html

有需要的可以直接copy下面代码。

PS,发现cocoawithlove.com里面文章质量都蛮高 ^_^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#define invokeSupersequent(...) \
    ([self getImplementationOf:_cmd after:impOfCallingMethod(self, _cmd)]) (self, _cmd  ,##__VA_ARGS__)

#define invokeSupersequentNoParameters() \
    ([self getImplementationOf:_cmd after:impOfCallingMethod(self, _cmd)]) (self, _cmd)



IMP impOfCallingMethod(id lookupObject, SEL selector)
{
    NSUInteger returnAddress = (NSUInteger)__builtin_return_address(0);
    NSUInteger closest = 0;

    // Iterate over the class and all superclasses
    Class currentClass = object_getClass(lookupObject);
    while (currentClass)
    {
        // Iterate over all instance methods for this class
        unsigned int methodCount;
        Method *methodList = class_copyMethodList(currentClass, &methodCount);
        unsigned int i;
        for (i = 0; i < methodCount; i++)
        {
            // Ignore methods with different selectors
            if (method_getName(methodList[i]) != selector)
            {
                continue;
            }

            // If this address is closer, use it instead
            NSUInteger address = (NSUInteger)method_getImplementation(methodList[i]);
            if (address < returnAddress && address > closest)
            {
                closest = address;
            }
        }

        free(methodList);
        currentClass = class_getSuperclass(currentClass);
    }

    return (IMP)closest;
}

@interface  NSObject (SupersequentImplementation)
- (IMP)getImplementationOf:(SEL)lookup after:(IMP)skip;
@end

@implementation NSObject (SupersequentImplementation)

// Lookup the next implementation of the given selector after the
// default one. Returns nil if no alternate implementation is found.
- (IMP)getImplementationOf:(SEL)lookup after:(IMP)skip
{
    BOOL found = NO;

    Class currentClass = object_getClass(self);
    while (currentClass)
    {
        // Get the list of methods for this class
        unsigned int methodCount;
        Method *methodList = class_copyMethodList(currentClass, &methodCount);

        // Iterate over all methods
        unsigned int i;
        for (i = 0; i < methodCount; i++)
        {
            // Look for the selector
            if (method_getName(methodList[i]) != lookup)
            {
                continue;
            }

            IMP implementation = method_getImplementation(methodList[i]);

            // Check if this is the "skip" implementation
            if (implementation == skip)
            {
                found = YES;
            }
            else if (found)
            {
                // Return the match.
                free(methodList);
                return implementation;
            }
        }

        // No match found. Traverse up through super class' methods.
        free(methodList);

        currentClass = class_getSuperclass(currentClass);
    }
    return nil;
}

@end