由于C和C ++中的序列点,您遇到了哪些问题?

以下是由于序列点规则导致未定义行为的两个常见问题:

a[i] = i++; //has a read and write between sequence points i = i++; //2 writes between sequence points 

您在序列点方面遇到的其他事情是什么?

当编译器无法警告我们时,很难找到这些问题。

达里奥的一个例子是:

 void Foo(shared_ptr a, shared_ptr b){ ... } int main() { Foo(shared_ptr(new Bar), shared_ptr(new Bar)); } 

这可能会泄漏内存。 在评估两个参数之间没有序列点,因此不仅可以在第一个参数之前评估第二个参数,而且还可以在任何shared_ptr之前创建两个Bar对象。

也就是说,而不是被评估为

 Bar* b0 = new Bar(); arg0 = shared_ptr(b0); Bar* b1 = new Bar(); arg1 = shared_ptr(b1); Foo(arg0, arg1); 

(这将是安全的,因为如果成功分配b0 ,它会立即包装在shared_ptr ),它可以被评估为:

 Bar* b0 = new Bar(); Bar* b1 = new Bar(); arg0 = shared_ptr(b0); arg1 = shared_ptr(b1); Foo(arg0, arg1); 

这意味着如果b0成功分配,并且b1抛出exception,则b0永远不会被删除。

关于参数列表中的执行顺序或例如添加,存在一些不明确的情况。

 #include  using namespace std; int a() { cout << "Eval a" << endl; return 1; } int b() { cout << "Eval b" << endl; return 2; } int plus(int x, int y) { return x + y; } int main() { int x = a() + b(); int res = plus(a(), b()); return 0; } 

首先执行()或b()吗? 😉

以下是Bjarne Stroustup使用c ++编写原则和实践的简单规则

“如果更改表达式中变量的值。不要在同一个表达式中读取或写入两次”

 a[i] = i++; //i's value is changed once but read twice i = i++; //i's value is changed once but written twice 

类似于Dario的一个例子,我也看到人们陷入其中:

 printf("%s %s\n", inet_ntoa(&addr1), inet_ntoa(&addr2)); 

这不仅会打印“ addr1 addr1 ”或“ addr2 addr2 ”(因为inet_ntoa返回指向静态缓冲区的指针,这些指针会被其他调用覆盖),但也没有定义它们中的哪一个(因为C没有指定)参数列表中的评估顺序)。

这里有两个适用于大多数C编译器的好表达式,但由于序列点而不明确:

 x ^= y ^= x ^= y; // in-place swap of two variables 

并且

 int i=0; printf("%d %d %d", ++i, ++i, ++i); // usually prints out 3 2 1... but not for all compilers! 

我最近看到的那个是由于程序员希望节省类格式化时间,完全是错误的:

class A { public: ... const char* Format( const string& f ) const { fmt = Print( f, value ); return fmt.c_str(); } operator const char* () const { return fmt.c_str(); } private: struct timeval value; mutable string fmt; }; A a( ... ); printf( "%s %s\n", a.Format( x ), a.Format( y );
class A { public: ... const char* Format( const string& f ) const { fmt = Print( f, value ); return fmt.c_str(); } operator const char* () const { return fmt.c_str(); } private: struct timeval value; mutable string fmt; }; A a( ... ); printf( "%s %s\n", a.Format( x ), a.Format( y ); 

最后一行要么总是为两种格式打印相同的值(要么使程序崩溃,因为内部字符串会释放返回的内存)。

另一个是我很久以前的一次采访:

 void func( int x, int y, int z ) { printf( "%d %d %d\n", x, y, z ); } ... int i = 0; func( i, ++i, i++ ); /* don't do this in real software :) */