C++ 低级错误(持续更新中ing)

typedef struct __sInotifyPath  // 路径结构体
{
 char cInotifyType;
 uint32_t  sInotifyext;
 uint32_t  iInotifyID;
 string name;
 uint32_t ilevel;
}sInotifyPath;

使用memset对结构体进行初始化,导致在对成员变量赋值是崩溃

用memset将结构体中的所有比特都置为0。这两天写个测试工具,里面有个结构体,成员有一个std::string类型的对象。使用memset填充完之后,给结构体中的字符串成员变量赋值,居然引起了崩溃。怎么回事?跟了跟代码,发现在STL内部实现赋值的时候崩溃。第一直觉就是使用了,空指针。这时候突然看到了前面对memset的调用,赶紧注掉试试,问题消失了。

现在终于明白为什么coding rule上说结构体中最好只放内置类型的成员了。内置类型是可以memset填充的,但是类就不可以了,尤其是有指针成员的类。在类构造的时候,指针会new出空间,但是之后被填零,指针变成空指针了,然后程序崩溃的悲惨结局发生了……

教训:使用memset对内置类型进行填充。

 

自动对象的存储分配发生在定义它的函数被调用是。分配给自动变量的存储区来自程序的运行栈,他是函数的活动记录的一部分 。未初始话化的自动对象包含一个随机的位模式,是该存储去上次被使用的结果,值是不确定的

如果没有提供初试值,全局的,名字空间的和局静态对象会被自动的初试化为适当类型的0。

教训:局部变量使用前必须初始化,包括类的成员变量,缺省构造函数不会对类成员变量进行初始化

 

The  four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not
  thread-safe.  Thread-safe versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are  specified  by  SUSv2,
  and available since libc 5.2.5.

教训:求时间的函数返回静态数据是线程非安全,使用要谨慎。

 

inet_ntoa

仔细看一下inet_ntoa的man,我们可以看到这句话:The string is returned in a statically allocated buffer, which subsequent calls will overwrite. 证实了我们的分析。

小结
让我们大家都扪心自问一下,我们在写程序的过程当中是否使用了这种方法?这是一个比较危险,容易出错的方法。这种陷阱让人防不胜防。想想,如果你有这样的程序:
    if ( strcmp( inet_ntoa(ip1), inet_ntoa(ip2) )==0 ) {
        .... ....
   }
本想判断一下两个IP地址是否一样,却不料掉入了那个陷阱——让这个条件表达式永真。

这个事情告诉我们下面几个道理:
1)慎用这种方式的设计。返回函数内部的static内存有很大的陷阱。
2)如果一定要使用这种方式的话。你就必须严肃地告诉所有使用这个函数的人,千万不要在一个表达式中多次使用这个函数。而且,还要告诉他们,不copy函数返回的内存的内容,而只是保存返回的内存地址或是引用是没用的。不然的话,后果概不负责。

教训:inet_ntoa这类函数 返回指向static buf的指针,这个是线程不安全的,同时间函数

你可能感兴趣的:(C,C++,c++,测试工具,string,存储,struct,buffer)