搜尋

首頁  >  問答  >  主體

c++ - 多线程下对一个串多次调用strok后strlen报段错误

while(1)
{
    char buf[800] ={0};
    ret=fgets(buf, sizeof(buf) -1, fp);
    if(!ret){ 
    ...lseek to head of file
    continue;
    }
    //问题很可能出在这里,改成strtok_r还是会同样出错
    char *url=strtok(buf,"\n");
    index++;
    thread=&stk_threads[index];
    stk_thread_push_task(thread, url);

    if(++index==max_thread)
    {
       index=0;
    }
}

先贴代码如上,问题如下
程序在对一个文件遍历一段时间(我确定还没遇到过尾部)之后,在push到选定thread的队列时【主程序会用strlen判断url处(来源指针)的字串长度,从而拷贝一份出来,防止各线程读到重复的url内容】在strlen时候报段错误。

我知道strtok的实现原理,但是不明白这个段错误在这个情形下发生的具体原因是什么呢?【注意,执行strtok和push到选定线程以及调用strlen拷贝源串的都是主线程自己】

伊谢尔伦伊谢尔伦2804 天前603

全部回覆(2)我來回復

  • 大家讲道理

    大家讲道理2017-04-17 11:36:07

    url 是指向一個全域共享內存,你的線程還沒有處理,push 到隊列裡面的指針就已經被下一次 strtok 呼叫給破壞掉,如果再訪問這些指針就會段錯誤。

    改用 strtok_r 就好了。

    回覆
    0
  • 黄舟

    黄舟2017-04-17 11:36:07

    我的理解是: char buf[800] 分配在主線程的棧空間上, 而每次strtok 後, url 指向buf 的地址. 所以對子線程來說, 這裡存在 Cross-thread Stack Access.

    https://software.intel.com/sites/products/documentation/hpc/inspectorxe/en-us/2011Update/lin/ug_docs/GUID-F0B0D34B-6691-4033-931F-GUID-F0B0D34B-6691-4033-931F-4BBBD1A1F791.

    無濟於事. 試著 每次在把 url 的內容 在堆裡拷貝一份, 傳給 子線程, 然後 delete 掉.strtok_r 當然更好的辦法是在 線程 資料結構裡 給 url 分配對應的記憶體.

    回覆
    0
  • 取消回覆