1.使用刚被删除的对象指针,由于该块内存仍然有效,不会发生页访问错误,程序继续正常运行,直到有对象分配到该块内存,错误爆发。使用构造分配内存,析构释放内存的类对象,容易有此问题,应避免该做法。特别,若内存处有stl容器,有可能会破坏整个stl的分配器,导致所有stl容器发生不可预测逻辑的行为。
2.VC SP5的MFCO42.dll与原VC版本有重大差别,使用SP5和不使用SP5的程序DLL若涉及该DLL,程序发生不可预测逻辑行为。
3.用新版本DLL替换旧版本DLL,出错。推论:新版本有错。
该推论不成立。客户端程序的隐藏错误可能影响DLL内对象的运行,其在旧DLL不会发作,而新DLL二进制Image变化,内存分配变动, 使得隐藏错误发挥效果,程序崩溃。
4.程序出错后,无正常逻辑可言,应先予排除所有次要或有干扰的原因,最后跟踪主要原因。
5.在调试时需要被try catch的异常崩出,Debug->Exceptiion->Stop Alway.
6.Release版,客户机运行崩溃。出call map,记下崩溃地址,从map中查找。
7.void Test()
{
try{
int* p = NULL;
*p = 10;
}
catch(...)
{
printf("Error in Test");
}
}
int main()
{
try
{
Test();
}
catch(...)
{
printf("Error in main");
}
}
Debug版Test出错,Release版main出错,即try catch不能有效地防止空指针崩溃.
8.pragma pack(push, 1)没有pop,再写一个pragma pack(push, 1),编译期结构对齐将完全混乱,得出的运行期的地址将和编译期推算完全不符,轻则疯狂,重则吐血。
9.全局模板函数,使用策略式参数,编译出的函数,永远都是最后一个被实例化的函数,而非根据模板参数的函数,吐血问候写编译器的那位。
struct A
{
void test()
{
int f = 0;
}
};
struct B
{
void test()
{
double g = 0.1;
}
};
template<typename mytype>
void Test()
{
mytype k;
k.test();
}
int main(int argc, char* argv[])
{
Test<A>();
Test<B>();
printf("Hello World!\n");
return 0;
}
调用的都是B::test()
10.换行的文本在Watch中显示没有换行,在tip中换行,导致判断错误.
11.编辑器换行符\后不能有tab制表符,负责文本解析混乱出错.