C++ string類賦值並發問題


前一段排查產品的一個異常問題,是有關C++ string類的,做字符串賦值操作時,應用程序崩潰了。

堆棧信息如下:

 

 

經過分析代碼,發現同一個字符串變量會在多個線程里做賦值操作,而且沒有加鎖保護。

string類字符串賦值操作是線程不安全的,當多個線程同時對同一個string類變量做賦值操作時,就會產生異常。

 

一般來說,聲明string變量時(不做賦值,或者字符串長度為0),string對象內會有一個保存字符串的地址,其內存長度為0;

當再次賦值一個較長字符串時,string對象會重新從堆中分配一段地址存放內容,釋放之前聲明時產生的內存地址。

先看一個簡單的string 初始化例子:

 1 #include <string>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <stdio.h>
 5 
 6 using std::string;
 7 
 8 int main(int argc, const char* argv[])
 9 {
10     string localstr="";
11     if(localstr.empty())
12         printf("localstr empty: %s\n", localstr.c_str());
13 
14    
15    printf("c_str = %p, capacity = %d, size = %d\n", localstr.c_str(), localstr.capacity(), localstr.size());
16    localstr = "hello world!";
17    printf("c_str = %p, capacity = %d, size = %d\n", localstr.c_str(), localstr.capacity(), localstr.size());
18 
19    return 0;
20 }

打印輸出:

1 c_str = 0x602028, capacity = 5, size = 5
2 c_str = 0x602058, capacity = 12, size = 12

 

如果是多個線程同時對同一個string對象做賦值操作,在沒有任何鎖保護情況下,會產生異常。

示例代碼核心部分:

 1 string  test_str1;
 2 string    test_str2;
 3 
 4 void *string_test_thread_ex(void *p)
 5 {    
 6     struct sched_param  curr_param;
 7     
 8     prctl(PR_SET_NAME, "string_test");
 9 
10 
11     NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF);
12     if(NUM_PROCS == -1)
13     {
14         printf("failed to get cpu nums: %s(%d)\n", strerror(errno), errno);
15         NUM_PROCS = DEF_CPU_NUM;
16     }
17 
18     CPU_ZERO(&cpuset);
19     cpuidx = (curnum++)%NUM_PROCS;
20     CPU_SET(cpuidx, &cpuset);
21     if (pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset))
22     {
23         perror("pthread_setaffinity_np");
24     }
25     while(1)
26     {
27         test_str1 = "hello world1";
28         test_str2 = "hello world2";
29 
30         usleep(50);
31     }
32   
33 }

 

運行結果:

 1 now create the thread:
 2 *** glibc detected *** ./stringtest: double free or corruption (fasttop): 0x00007f8de80009f0 ***
 3 ======= Backtrace: =========
 4 /lib64/libc.so.6(+0x73ee8)[0x7f8dfe281ee8]
 5     0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15
 6 /lib64/libc.so.6(cfree+0x6c)[0x7f8dfe286d6c]
 7 /usr/lib64/libstdc++.so.6(_ZNSs9_M_mutateEmmm+0x1c3)[0x7f8dfeaf2a03]
 8 /usr/lib64/libstdc++.so.6(_ZNSs15_M_replace_safeEmmPKcm+0x2c)[0x7f8dfeaf2a3c]
 9 ./stringtest[0x40237a]
10 /lib64/libpthread.so.0(+0x79ed)[0x7f8dfef5b9ed]
11 /lib64/libc.so.6(clone+0x6d)[0x7f8dfe2ea14d]

 

異常堆棧信息和本文開頭的不一樣,但都是由string對象的並發操作導致APP運行異常。

 

 

參考資料:

https://my.oschina.net/u/4000302/blog/4469522

https://blog.csdn.net/cny901111/article/details/7771668

 

您的支持是對博主最大的鼓勵👍,感謝您的認真閱讀。

本博客持續更新,歡迎您關注和交流!


本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM