m_pFile 无法识别的内存

本文探讨了在实际编程中,特别是在C++环境下,不当使用指针可能导致的问题。通过一个具体的案例,即在B类中使用指针指向A类实例,作者发现这可能导致A类中的某些指针无法正确分配内存,进而引发运行时错误。文章建议,除非绝对必要,否则应避免使用指针,并提供了可能的解决方案。

参考文章(类似问题:自动的vector在pushback的时候size变为0

别使用没有必要的指针

………………

代码接下来补充

测试了下代码,demo写出来不报错,这个实在实际工作中遇到的,具体解决方案就是上面的一句话,如果没有必要不要使用指针,其实这是半句话,不要随便写想 Cstring 的构造函数和copy构造函数那样的写法。

出现问题的场景

有AB两个类,在B类中调用A类,其中A的实线未知,有相关的lib以及头文件且已经链接。

由于在B中的构造函数很骚的来了个new以及成员变量来了个很骚的 A * a;导致出现问题,但是自己回家后试着写了这样的demon并没有报错,通过new跟踪变量的时候发现A类中有一个 m_pFile  指针始终无法获得空间,但是将指针全部取消,该问题就不存在在

猜测

1、A类的实现绝壁有Bug……(没有运算符没有重载

2、指针重名

``` int CSocketClientJNMES::SendMTFData(const string & info, string & resultMSG, const string & hostname, const int & port, const string & apiPath) { CInternetSession session(_T("MyPostAgent")); try { CHttpConnection* pServer = session.GetHttpConnection ( m_GFunction.String2CString(hostname), port, _T(""), _T("") ); m_Loger.RecordLogTcpClientJNURL("hostname:" + hostname + "port:" + to_string(port) + "CHttpConnection* pServer"); CHttpFile* pFile = pServer->OpenRequest ( CHttpConnection::HTTP_VERB_POST, m_GFunction.String2CString(apiPath) ); m_Loger.RecordLogTcpClientJNURL(apiPath + "CHttpFile* pFile = pServer->OpenRequest"); CString strHeaders = _T("Content-Type: application/json"); CString strData = m_GFunction.String2CString(info); m_Loger.RecordLogTcpClientJNURL("info:" + info); pFile->SendRequest ( strHeaders, (DWORD)strHeaders.GetLength(), (LPVOID)(LPCTSTR)strData, (DWORD)strData.GetLength() ); m_Loger.RecordLogTcpClientJNURL("pFile->SendRequest"); DWORD dwStatusCode; pFile->QueryInfoStatusCode(dwStatusCode); CString strResponse; if (dwStatusCode == HTTP_STATUS_OK) { TCHAR szBuffer[1024]; while (pFile->Read(szBuffer, 1023) > 0) { strResponse += szBuffer; } AfxMessageBox(strResponse); } resultMSG = m_GFunction.CString2String(strResponse); m_Loger.RecordLogTcpClientJNURL("resultMSG:" + resultMSG); pFile->Close(); delete pFile; delete pServer; } catch (CInternetException* pEx) { TCHAR szError[1024]; pEx->GetErrorMessage(szError, 1024); AfxMessageBox(szError); pEx->Delete(); } return 0; }```分析代码并优化
04-05
int Player::Play(int argc, char* argv[]) { int RetValue=0; try { try { // Parse command line options m_CmdLineParams.Init(); m_CmdLineParams.ParseCommandLine(argc, argv); } catch ( Exc e ) { Log(e, true); Log("", true); Log("Use -? option for help--Exc", true); return -1; } catch (DtOptException e) { Log(e, true); Log("", true); Log("Use -? option for help--DtOptException", true); return -1; } catch ( ... ) { return -1; } if ( m_CmdLineParams.m_ShowHelp ) { // Disable silent mo de m_CmdLineParams.m_SilentMode = false; ShowHelp(); return RetValue; } //-.-.-.-.-.-.-.-.-.-.-.-.-.-.- Print start message -.-.-.-.-.-.-.-.-.-.-.-.-.-.-. LogF("DtPlay player V%d.%d.%d (c) 2000-2019 DekTec Digital Video B.V.\n", DTPLAY_VERSION_MAJOR, DTPLAY_VERSION_MINOR, DTPLAY_VERSION_BUGFIX); LogF("DTAPI compile version: V%d.%d.%d.%d\n", DTAPI_VERSION_MAJOR, DTAPI_VERSION_MINOR, DTAPI_VERSION_BUGFIX, DTAPI_VERSION_BUILD); int Maj=-1,Min=-1,BugFix=-1,Build=-1; DtapiGetVersion(Maj,Min,BugFix,Build); LogF("DTAPI link version: V%d.%d.%d.%d\n", Maj, Min, BugFix, Build); //.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- Open the play file -.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // Try to open a file for reading if (!m_CmdLineParams.m_FileName.empty()) { // 仅当文件名非空时尝试打开 #ifdef WINBUILD LogF("open ts file %ls\n", m_CmdLineParams.m_FileName.c_str()); m_pFile = _wfopen(m_CmdLineParams.m_FileName.c_str(), L"rb"); #else string StrFilename(m_CmdLineParams.m_FileName.begin(), m_CmdLineParams.m_FileName.end()); m_pFile = fopen(StrFilename.c_str(), "rb"); #endif if (m_pFile == NULL) throw Exc(c_ErrFailToOpenFile, m_CmdLineParams.m_FileName.c_str()); //.-.-.-.-.-.-.-.-.-.-.-.-.-.- Auto detect SDI format -.-.-.-.-.-.-.-.-.-.-.-.-.-. if (m_CmdLineParams.m_PlayDtSdiFile) AutoDetectSdiFormat(); else if (m_CmdLineParams.m_PlayPcapFile) DetectPcapFormat(); } //-.-.-.-.-.-.-.-.-.-.-.-.- Attach to the output channel -.-.-.-.-.-.-.-.-.-.-.-.- AttachToOutput(); //-.-.-.-.-.-.-.-.-.-.-.-.-.-.- Final initialisation -.-.-.-.-.-.-.-.-.-.-.-.-.-.- // Init output InitOutput(); // Create our transfer buffer m_pBuf = new char [c_BufSize]; //.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- Start playing -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // Print start info DisplayPlayInfo(); // Loop file if (m_pFile != NULL) { //2025-8-20 modified LoopFile(); } else { 新建接收线程和输入速率计算线程 } } catch( Exc e ) { Log(e, true); RetValue = -1; } #ifdef WINBUILD WSACleanup(); // 清理Winsock #endif // Detach from channel and device m_DtOutp.SetTxControl(DTAPI_TXCTRL_IDLE); m_DtOutp.Detach(DTAPI_INSTANT_DETACH); m_DtDvc.Detach(); // Free our buffer if ( m_pBuf != NULL ) { delete [] m_pBuf; m_pBuf = NULL; } // donot forget to close our file if ( m_pFile != NULL ) { ::fclose(m_pFile); m_pFile = NULL; } return RetValue; },基于现有这段代码中的情况,现需要实现当m_pFile != NULL时执行LoopFile();,否则(else)就新建一个UDP接收线程和输入速率计算线程,通过UDP接收来自组播地址{地址:"236.78.78.84", 端口:59000}的节目流数据,将接收到的数据存起来(比如calcbuffer或者calc vector,或者calc 队列,具体选择哪种需要综合考虑效率以及开销,是否容易溢出等)。在计算输入速率的线程里,需要把接收线程里寻下来的数据全都给DTMP2API::EstimateTsRate(UInt8* pBuf, Int BufSize)的 pBuf来计算输入速率,第一次计算出来速率后,之后每隔五秒计算一次,DTMP2API::EstimateTsRate(UInt8* pBuf, Int BufSize)此函数的实现已有,无需生成,并且要能实现在运行的过程中如果检测到有任意按键摁下,就停止程序
最新发布
09-06
```cpp #include <iostream> #include <cstring> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <pthread.h> #include <fcntl.h> #include <queue> // 假设的 LoopFile 函数 void LoopFile() { std::cout << "Executing LoopFile()" << std::endl; // 这里可以添加 LoopFile 的具体实现 } // 假设的 DTMP2API 命名空间和 EstimateTsRate 函数 namespace DTMP2API { int EstimateTsRate(unsigned char* pBuf, int BufSize) { // 检查有效缓冲区(至少有100个数据包) if (pBuf == nullptr || BufSize < (204 * 100)) return -1; // 首先尝试同步 int PckSize = 188, OffsetToFirstPacket = 0; // 假设的 Synchronise 函数 // if (!Synchronise(pBuf, BufSize, PckSize, OffsetToFirstPacket)) // return -1; // 查找具有 PCR 的 PID 并根据 PCR 计算比特率 int i = 0, PcrPid = -1, SeqNumFirstPcr, NumPcr = 0, PcrTsRate = -1, pcridt = 0; std::cout << "OffsetToFirstPacket=" << OffsetToFirstPacket << std::endl; unsigned char* pTp = pBuf + OffsetToFirstPacket; // 假设的 Mp2s::PCR 结构体和相关函数 // Mp2s::PCR FirstPcr, FourtPCR, SecondPcr, ThirdPcr; for (i; i < (BufSize - OffsetToFirstPacket); i += PckSize, pTp += PckSize) { if (*pTp != 0x47) continue; // 检查 PCR // if (!Mp2s::TpHoldsPcr(pTp)) // continue; // 跳过非 PCR PID // if (PcrPid != -1 && PcrPid != Mp2s::TpGetPid(pTp)) // continue; // 检查不连续性 // if (PcrPid == Mp2s::TpGetPid(pTp) && Mp2s::TpDiscontinuityIndicator(pTp)) { // PcrPid = -1; // continue; // } // 获取第一个 PCR // if (PcrPid == -1) { // FirstPcr.GetFromTp(pTp); // PcrPid = Mp2s::TpGetPid(pTp); // std::cout << "FirstPcrPid=" << std::hex << PcrPid << std::endl; // SeqNumFirstPcr = i; // std::cout << "SeqNumFirstPcr=" << SeqNumFirstPcr << std::endl; // NumPcr++; // } else if (NumPcr >= 3) { // FourtPCR.GetFromTp(pTp); // double DeltaT = static_cast<double>(FourtPCR - FirstPcr); // double NumTp = static_cast<double>(i - SeqNumFirstPcr); // std::cout << "DeltaT=" << DeltaT << std::endl; // std::cout << "NumTp=" << NumTp << std::endl; // PcrTsRate = static_cast<int>((NumTp * 8.0) / (DeltaT / 27E6)); // if (PcrTsRate > 1000) // break; // else { // PcrPid = -1; // NumPcr = 0; // } // } else { // NumPcr++; // pcridt = Mp2s::TpGetPid(pTp); // std::cout << "PcrPid[" << NumPcr << "]=" << std::hex << pcridt << ", SeqNumFourtPcr=" << i << std::endl; // if (NumPcr == 2) { // SecondPcr.GetFromTp(pTp); // double DeltaT1 = static_cast<double>(SecondPcr - FirstPcr); // std::cout << "DeltaT1=" << DeltaT1 << std::endl; // } // if (NumPcr == 3) { // ThirdPcr.GetFromTp(pTp); // double DeltaT2 = static_cast<double>(ThirdPcr - SecondPcr); // std::cout << "DeltaT2=" << DeltaT2 << std::endl; // } // } } // 补偿非 188 字节数据包 // PcrTsRate = static_cast<int>(static_cast<double>(PcrTsRate) * 188.0 / static_cast<double>(PckSize)); return PcrTsRate; } } // 全局变量 void* m_pFile = nullptr; bool running = true; std::queue<unsigned char> dataQueue; pthread_mutex_t queueMutex; // UDP 接收线程函数 void* udpReceiver(void* arg) { int sockfd; struct sockaddr_in localAddr, groupAddr; struct ip_mreq mreq; // 创建套接字 sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); return nullptr; } // 绑定本地地址 memset(&localAddr, 0, sizeof(localAddr)); localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = INADDR_ANY; localAddr.sin_port = htons(59000); if (bind(sockfd, (struct sockaddr*)&localAddr, sizeof(localAddr)) < 0) { perror("bind"); close(sockfd); return nullptr; } // 设置组播地址 memset(&groupAddr, 0, sizeof(groupAddr)); groupAddr.sin_family = AF_INET; groupAddr.sin_addr.s_addr = inet_addr("236.78.78.84"); groupAddr.sin_port = htons(59000); // 加入组播组 mreq.imr_multiaddr.s_addr = inet_addr("236.78.78.84"); mreq.imr_interface.s_addr = INADDR_ANY; if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { perror("setsockopt"); close(sockfd); return nullptr; } char buffer[1024]; socklen_t addrLen = sizeof(groupAddr); while (running) { ssize_t recvLen = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&groupAddr, &addrLen); if (recvLen > 0) { pthread_mutex_lock(&queueMutex); for (ssize_t i = 0; i < recvLen; ++i) { dataQueue.push(buffer[i]); } pthread_mutex_unlock(&queueMutex); } } close(sockfd); return nullptr; } // 输入速率计算线程函数 void* rateCalculator(void* arg) { bool firstCalculation = true; while (running) { if (firstCalculation) { // 首次计算 firstCalculation = false; } else { sleep(5); // 每五秒计算一次 } pthread_mutex_lock(&queueMutex); int bufferSize = dataQueue.size(); unsigned char* buffer = new unsigned char[bufferSize]; for (int i = 0; i < bufferSize; ++i) { buffer[i] = dataQueue.front(); dataQueue.pop(); } pthread_mutex_unlock(&queueMutex); int rate = DTMP2API::EstimateTsRate(buffer, bufferSize); std::cout << "Input rate: " << rate << " bps" << std::endl; delete[] buffer; } return nullptr; } int main() { pthread_mutex_init(&queueMutex, nullptr); if (m_pFile != nullptr) { LoopFile(); } else { pthread_t receiverThread, calculatorThread; // 创建 UDP 接收线程 if (pthread_create(&receiverThread, nullptr, udpReceiver, nullptr) != 0) { perror("pthread_create (udpReceiver)"); return 1; } // 创建输入速率计算线程 if (pthread_create(&calculatorThread, nullptr, rateCalculator, nullptr) != 0) { perror("pthread_create (rateCalculator)"); return 1; } std::cout << "Press any key to exit..." << std::endl; std::cin.get(); // 按任意键退出 running = false; // 等待线程结束 pthread_join(receiverThread, nullptr); pthread_join(calculatorThread, nullptr); } pthread_mutex_destroy(&queueMutex); return 0; } ``` ### 代码说明: 1. **`LoopFile` 函数**:当 `m_pFile` 不为空时,执行该函数,当前仅输出提示信息,可根据实际需求添加具体逻辑。 2. **`udpReceiver` 函数**:创建 UDP 套接字,绑定本地地址,加入组播组,接收组播地址 `236.78.78.84:59000` 的数据,并将数据存入 `dataQueue` 队列中。 3. **`rateCalculator` 函数**:首次计算输入速率后,每五秒计算一次。从 `dataQueue` 中取出数据,调用 `DTMP2API::EstimateTsRate` 函数计算输入速率。 4. **`main` 函数**:根据 `m_pFile` 的值决定执行 `LoopFile` 函数或创建 UDP 接收线程和输入速率计算线程。按任意键退出程序。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焰川

微信 2936729162

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值