返回信息流我知道C的静态局部变量是线程不安全的,但最近写的一个程序coredump了,调试定位在这个静态局部变量(没有加锁)的赋值处。问题是:在多线程环境下,使用未加锁静态局部变量是否会导致程序coredump?具体原因是什么?
这是一条镜像帖。来源:北邮人论坛 / cpp / #95990同步于 2017/8/14
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
【问题】关于C静态局部变量
yeahfeng
2017/8/14镜像同步8 回复
订阅后,新回复会通过你的通知中心匿名送达。
8 条回复
c++的类的静态局部变量是线程安全的,我从网上查的c的好像不是?
【 在 nuanyangyang 的大作中提到: 】
: 谁说静态局部变量是线程不安全的?
:
发自「贵邮」
关键问题是后面那个,我写了个测试小程序,多线程里静态局部变量确实会导致coredump,报错double free and corruption,这就又不懂了,静态局部变量不是在程序终止的时候才会释放吗,为什么一运行就崩掉呢?当然你能够纠正一下我前面的问题也是非常感谢的!
【 在 nuanyangyang 的大作中提到: 】
: 谁说静态局部变量是线程不安全的?
:
发自「贵邮」
这么回答吧:不论是C还是C++,多个线程,在没有使用锁,也没有使用其他同步机制的情况下,访问一个共享的存储空间(不论是静态变量、全局变量,还是堆内存),而且这个存储空间也不是atomic_int等原子类型,而且两个线程的操作中有一个操作是写操作,那么结果就是“未定义行为”,就是任何结果都可以发生,从什么都不发生到机器冒烟都是可以的。coredump是比较温和的结果。
想让机器不冒烟,就看看C++11的thread和mutex怎么用。
http://en.cppreference.com/w/cpp/thread/thread
http://en.cppreference.com/w/cpp/thread/mutex
这是最简单的。还可以看condition variable,也可以看future和promise。
原子内存操作(atomic<xxxx>)是高级话题。
【 在 yeahfeng 的大作中提到: 】
: 我知道C的静态局部变量是线程不安全的,但最近写的一个程序coredump了,调试定位在这个静态局部变量(没有加锁)的赋值处。问题是:在多线程环境下,使用未加锁静态局部变量是否会导致程序coredump?具体原因是什么?
受教了,原来是“未定义的行为”,我以为只会导致共享存储区变量结果的不可预期!下面我把那个代码贴一下吧,就是json解析库jsonxx上的一个小函数,不知道它为什么没有考虑线程的问题。
【 在 nuanyangyang 的大作中提到: 】
: 这么回答吧:不论是C还是C++,多个线程,在没有使用锁,也没有使用其他同步机制的情况下,访问一个共享的存储空间(不论是静态变量、全局变量,还是堆内存),而且这个存储空间也不是atomic_int等原子类型,而且两个线程的操作中有一个操作是写操作,那么结果就是“未定义行为”,就是任何结果都可以发生,从什么都不发生到机器冒烟都是可以的。coredump是比较温和的结果。
: 想让机器不冒烟,就看看C++11的thread和mutex怎么用。
: http://en.cppreference.com/w/cpp/thread/thread
: ...................
std::string escape_string( const std::string &input, const bool quote = false ) {
static std::string map[256], *once = 0;
if( !once ) {
// base
for( int i = 0; i < 256; ++i ) {
map[ i ] = std::string() + char(i);
}
// non-printable
for( int i = 0; i < 32; ++i ) {
std::stringstream str;
str << "\\u" << std::hex << std::setw(4) << std::setfill('0') << i;
map[ i ] = str.str();
}
// exceptions
map[ byte('"') ] = "\\\"";
map[ byte('\\') ] = "\\\\";
map[ byte('/') ] = "\\/";
map[ byte('\b') ] = "\\b";
map[ byte('\f') ] = "\\f";
map[ byte('\n') ] = "\\n";
map[ byte('\r') ] = "\\r";
map[ byte('\t') ] = "\\t";
once = map;
}
std::string output;
output.reserve( input.size() * 2 + 2 ); // worst scenario
if( quote ) output += '"';
for( std::string::const_iterator it = input.begin(), end = input.end(); it != end; ++it )
output += map[ byte(*it) ];
if( quote ) output += '"';
return output;
}
这绝对是线程不安全的代码。你可以给他们报告bug了。
【 在 yeahfeng 的大作中提到: 】
: 受教了,原来是“未定义的行为”,我以为只会导致共享存储区变量结果的不可预期!下面我把那个代码贴一下吧,就是json解析库jsonxx上的一个小函数,不知道它为什么没有考虑线程的问题。