悬垂引用


int
C::RecordDownload(string taskid,string channel, string fileName, int filetype, string begintime, string endtime) { if (fileName == "") { app_log(LOG_DEBUG, "RecordDownload file name error\r\n"); return - 1; } _dhdev_lapi_info* _lapi_info_ptr = GetLapiInfo(_dhdev_comand::_default_cmd); if (_lapi_info_ptr == nullptr) return -1; shared_ptr<_dhdev_cmd_info> _cmd_ptr = InitCommandInfo(_lapi_info_ptr); _cmd_ptr->_lapi_info._cmd_method = "GET"; char _cmd_str_ptr[200] = { 0 }; sprintf(_cmd_str_ptr, "/cgi-bin/loadfile.cgi?action=startLoad&channel=%s&startTime=%s&endTime=%s&subtype=0&Types=dav", channel.c_str(), begintime.c_str(),endtime.c_str()); 。。。。。 //可能对应多个下载过程。所以线程对象也是有多个 pthread_t threadptr; _cmd_ptr->_taskId = taskid; thread_create(&threadptr, DownThreadProc, this);//第一个参数需要一个对象,而不是指针,要有内存位置 { _down_lock_mtx.lock(); DownMap.insert({ taskid, {&threadptr, _cmd_ptr}}); _down_lock_mtx.unlock(); } return 1; } int C::SetDownloadCB(Proxy_DownloadCallback cbFun, void* pUser) { _downCb = cbFun; _pUser = pUser; return 1; } int C::StopRecordDownload(string teskid) { _down_lock_mtx.lock(); pthread_t* tempthread = NULL; std::map<string, std::pair<pthread_t*, std::shared_ptr<_dhdev_cmd_info>>>::iterator it; for (it = DownMap.begin(); it != DownMap.end(); it++) { if (strcmp( (it->first).c_str(), teskid.c_str()) == 0) { it->second.second->_download = false; tempthread = it->second.first; break; } } _down_lock_mtx.unlock(); //等待现成结束,销毁线程 Sleep(2000); if (tempthread) { thread_destroy(*tempthread);//会崩溃;因为线程对象已经没了 tempthread = NULL; } //删除map; _down_lock_mtx.lock(); it->second.first = NULL; it->second.second.reset(); DownMap.erase(it); _down_lock_mtx.unlock(); return 1; } int C::DownThreadProc(void* param) { C* Dhdevptr = (C*)param; std::shared_ptr<_dhdev_cmd_info> _cmd_ptr = nullptr; for (auto it = Dhdevptr->DownMap.begin(); it != Dhdevptr->DownMap.end(); ++it) { if (thread_isself(*(it->second.first)) && it->second.second != nullptr) { _cmd_ptr = it->second.second; break; } } if (_cmd_ptr == nullptr) { return 0; } int _rtn_value = Dhdevptr->SendLapiCommand(_cmd_ptr, nullptr, 0); if (_rtn_value > 0) { if (_cmd_ptr->_response_ptr != nullptr) { if (strstr((char*)_cmd_ptr->_response_ptr, "OK") != nullptr) { return _rtn_value; } } } return _rtn_value; }

线程创建函数:

static inline int thread_create2(pthread_t* thread, unsigned int stacksize, thread_proc func, void* param)
{
#if defined(OS_WINDOWS)
    // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453.aspx
    // CreateThread function: By default, every thread has one megabyte of stack space. 

    // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx
    // A thread in an executable that calls the C run-time library (CRT) 
    // should use the _beginthreadex and _endthreadex functions for thread management 
    // rather than CreateThread and ExitThread;

    //thread->handle = CreateThread(NULL, stacksize, (LPTHREAD_START_ROUTINE)func, param, 0, &thread->id);
    typedef unsigned int(__stdcall *thread_routine)(void *);
    thread->handle = (HANDLE)_beginthreadex(NULL, stacksize, (thread_routine)func, param, 0, (unsigned int*)&thread->id);
    return NULL == thread->handle ? -1 : 0;
#else
    // https://linux.die.net/man/3/pthread_create
    // On Linux/x86-32, the default stack size for a new thread is 2 megabytes(10M 64bits)

    // http://udrepper.livejournal.com/20948.html
    // mallopt(M_ARENA_MAX, cpu); // limit multithread virtual memory
    typedef void* (*linux_thread_routine)(void*);
    int r;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setstacksize(&attr, stacksize);
    r = pthread_create(thread, &attr, (linux_thread_routine)func, param);
    pthread_attr_destroy(&attr);
    return r;
#endif
}

 

线程销毁函数

static inline int thread_destroy(pthread_t thread)
{
#if defined(OS_WINDOWS)
    if(thread.id != GetCurrentThreadId())
        WaitForSingleObjectEx(thread.handle, INFINITE, TRUE);
    CloseHandle(thread.handle);
    return 0;
#else
    void* value = NULL;
    if(pthread_equal(pthread_self(),thread))
        return pthread_detach(thread);
    else
        return pthread_join(thread, &value);
#endif
}

 

 再做录像下载功能的时候写了个悬垂引用,导致线程析构崩溃,无效线程句柄

--------https://blog.csdn.net/qq_21438461/article/details/135043382---------------------------------------------------------------------------------

在深入理解C++编程语言的同时,我们也在探索人类如何通过编程抽象地解决问题。悬垂引用(Dangling References)是这种探索的一个关键部分,它们不仅仅是技术问题,也反映了我们在思考和处理信息时可能遇到的挑战。
什么是悬垂引用
悬垂引用发生在引用继续指向一个已经释放或失效的内存地址时。可以把它想象成一个指向不存在目标的指针。就像在现实生活中,如果你试图访问一个已经被拆除的建筑,你会发现自己站在一个空地上,目标不复存在。

int* ptr;
{
    int x = 10;
    ptr = &x;
} // x 的作用域在这里结束
// 现在 ptr 成了一个悬垂指针,因为它指向的内存已经不再有效

悬垂引用主要由于以下几个原因造成:

    局部变量(对象)的引用保存成指针:当函数返回一个局部变量的引用时,该局部变量的生命周期随函数结束而结束,但引用仍然存在。
    对象的作用域结束:当对象的生命周期结束后,任何指向该(局部、临时)对象的引用都会变成悬垂引用。
    动态分配内存的错误管理:如果动态分配的内存被释放或删除,任何指向该内存的引用(指向该内存的指针)都会变悬垂

 

posted on 2024-05-15 19:34  邗影  阅读(7)  评论(0编辑  收藏  举报

导航