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 成了一个悬垂指针,因为它指向的内存已经不再有效
悬垂引用主要由于以下几个原因造成:
局部变量(对象)的引用保存成指针:当函数返回一个局部变量的引用时,该局部变量的生命周期随函数结束而结束,但引用仍然存在。
对象的作用域结束:当对象的生命周期结束后,任何指向该(局部、临时)对象的引用都会变成悬垂引用。
动态分配内存的错误管理:如果动态分配的内存被释放或删除,任何指向该内存的引用(指向该内存的指针)都会变悬垂
标签:悬垂,thread,int,cmd,引用,pthread,return,ptr From: https://www.cnblogs.com/8335IT/p/18194532