为什么在函数参数中使用赋值运算符会失败?
Why does this use of assignment operator in a function argument fail?
有人能指出为什么在下面的代码中,在传递给 write()
SIGSEGV 时使用具有 "return the rvalue" 样式的变量 p_char
吗?
#include <iostream>
#include <cerrno>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdint.h>
#include <sstream>
#include <stdexcept>
#define ASSERT( EXPRESSION, SOCKETPAIR ) \
{ \
if ( ! ( EXPRESSION ) ) \
{ \
std::ostringstream oss; \
oss << "Expression \"" << #EXPRESSION << "\" failed at line " << __LINE__ \
<< "; errno == " << errno << " (" << strerror( errno ) << ")"; \
throw MyException( oss.str(), SOCKETPAIR ); \
} \
}
class SocketPair
{
public:
SocketPair()
{
memset( socket_, -1, sizeof( socket_ ) );
}
int* operator()() { return socket_; }
int operator[]( const uint32_t idx )
{
if ( idx > 1 ) return -1;
return socket_[ idx ];
}
private:
int socket_[ 2 ];
};
class MyException : public std::runtime_error
{
public:
MyException( const std::string& what_arg, SocketPair& sp )
: runtime_error( what_arg )
, sp_( sp )
{}
SocketPair& sp_;
};
int main( int argc, char* argv[] )
{
SocketPair sp;
try
{
int result;
errno = 0;
result = socketpair( AF_LOCAL, SOCK_STREAM, 0, sp() );
ASSERT( result == 0, sp );
std::cout << "sp[0]==" << sp[0] << ", sp[1]==" << sp[1] << std::endl;
const char* p_char;
result = write( sp[ 1 ], ( p_char = "Hello?" ), strlen( p_char ) );
ASSERT( result == strlen( p_char ), sp );
}
catch ( MyException& e )
{
std::cout << e.what() << std::endl;
if ( e.sp_[ 0 ] >= 0 ) close( e.sp_[ 0 ] );
if ( e.sp_[ 1 ] >= 0 ) close( e.sp_[ 1 ] );
return 1;
}
close( sp[ 0 ] );
close( sp[ 1 ] );
return 0;
}
如果我更改以下两行...
const char* p_char;
result = write( sp[ 1 ], ( p_char = "Hello?" ), strlen( p_char ) );
...到此...
const char* p_char = "Hello?";
result = write( sp[ 1 ], p_char, strlen( p_char ) );
...然后程序不会发出 SIGSEGV 并正常退出。
编译在 gcc 4.8.3 和 4.9.2 (Code Chef) 上测试。
函数参数的求值顺序未定义(至少在 C++14 及更早版本中是这样)。
所以在
result = write( sp[ 1 ], ( p_char = "Hello?" ), strlen( p_char ) );
strlen( p_char )
可能会在 p_char = "Hello?"
之前求值,导致灾难。
有人能指出为什么在下面的代码中,在传递给 write()
SIGSEGV 时使用具有 "return the rvalue" 样式的变量 p_char
吗?
#include <iostream>
#include <cerrno>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdint.h>
#include <sstream>
#include <stdexcept>
#define ASSERT( EXPRESSION, SOCKETPAIR ) \
{ \
if ( ! ( EXPRESSION ) ) \
{ \
std::ostringstream oss; \
oss << "Expression \"" << #EXPRESSION << "\" failed at line " << __LINE__ \
<< "; errno == " << errno << " (" << strerror( errno ) << ")"; \
throw MyException( oss.str(), SOCKETPAIR ); \
} \
}
class SocketPair
{
public:
SocketPair()
{
memset( socket_, -1, sizeof( socket_ ) );
}
int* operator()() { return socket_; }
int operator[]( const uint32_t idx )
{
if ( idx > 1 ) return -1;
return socket_[ idx ];
}
private:
int socket_[ 2 ];
};
class MyException : public std::runtime_error
{
public:
MyException( const std::string& what_arg, SocketPair& sp )
: runtime_error( what_arg )
, sp_( sp )
{}
SocketPair& sp_;
};
int main( int argc, char* argv[] )
{
SocketPair sp;
try
{
int result;
errno = 0;
result = socketpair( AF_LOCAL, SOCK_STREAM, 0, sp() );
ASSERT( result == 0, sp );
std::cout << "sp[0]==" << sp[0] << ", sp[1]==" << sp[1] << std::endl;
const char* p_char;
result = write( sp[ 1 ], ( p_char = "Hello?" ), strlen( p_char ) );
ASSERT( result == strlen( p_char ), sp );
}
catch ( MyException& e )
{
std::cout << e.what() << std::endl;
if ( e.sp_[ 0 ] >= 0 ) close( e.sp_[ 0 ] );
if ( e.sp_[ 1 ] >= 0 ) close( e.sp_[ 1 ] );
return 1;
}
close( sp[ 0 ] );
close( sp[ 1 ] );
return 0;
}
如果我更改以下两行...
const char* p_char;
result = write( sp[ 1 ], ( p_char = "Hello?" ), strlen( p_char ) );
...到此...
const char* p_char = "Hello?";
result = write( sp[ 1 ], p_char, strlen( p_char ) );
...然后程序不会发出 SIGSEGV 并正常退出。
编译在 gcc 4.8.3 和 4.9.2 (Code Chef) 上测试。
函数参数的求值顺序未定义(至少在 C++14 及更早版本中是这样)。
所以在
result = write( sp[ 1 ], ( p_char = "Hello?" ), strlen( p_char ) );
strlen( p_char )
可能会在 p_char = "Hello?"
之前求值,导致灾难。