C++新手,求教为啥程序跑起来的内存越用越多

查看 101|回复 7
作者:albert0yyyy   
感觉好像是哪个变量申请了内存没有释放,然后越用越多,大概 20-30 来个请求增加 0.1G 的内存,我没有 delete 一些指针的话,增加的更快。
程序主要是通过 socket 通信,用 c++进行目标检测的这段代码。
op 只学过 c++的基本语法,平时做深度学习 python 用的比较多,所以 c++这边可能会欠缺一点,只能说把一些 bug 修复了能跑起来的水平。其实也是拿着官方 demo 改的,参数直接构造了一个 fake command ,见笑了
#include "jetson-utils/videoSource.h"
#include "jetson-utils/videoOutput.h"
#include "jetson-utils/imageLoader.h"
#include "jetson-inference/detectNet.h"
#include "jetson-inference/objectTracker.h"
#include "cJSON.h"
#include "jetson-utils/Socket.h"
#include
#include
using namespace std;
struct PredObj
{
        float x1;
        float y1;
        float x2;
        float y2;
        float score;
        int classID;
        float width;
        float height;
        const char *classDesc;
};
bool signal_recieved = false;
void sig_handler(int signo)
{
        if (signo == SIGINT)
        {
                LogVerbose("received SIGINT\n");
                signal_recieved = true;
        }
}
int usage()
{
        printf("usage: detectnet [--help] [--network=NETWORK] [--threshold=THRESHOLD] ...\n");
        printf("                 input [output]\n\n");
        printf("Locate objects in a video/image stream using an object detection DNN.\n");
        printf("See below for additional arguments that may not be shown above.\n\n");
        printf("positional arguments:\n");
        printf("    input           resource URI of input stream  (see videoSource below)\n");
        printf("    output          resource URI of output stream (see videoOutput below)\n\n");
        printf("%s", detectNet::Usage());
        printf("%s", objectTracker::Usage());
        printf("%s", videoSource::Usage());
        printf("%s", videoOutput::Usage());
        printf("%s", Log::Usage());
        return 0;
}
int main(int argc, char **argv)
{
        /*
         * parse command line
         */
        commandLine cmdLine(argc, argv);
        if (cmdLine.GetFlag("help"))
                return usage();
        /*
         * create detection network
         */
        detectNet *net = detectNet::Create(cmdLine);
        if (!net)
        {
                LogError("detectnet:  failed to load detectNet model\n");
                return 1;
        }
        // parse overlay flags
        const uint32_t overlayFlags = detectNet::OverlayFlagsFromStr(cmdLine.GetString("overlay", "box,labels,conf"));
        Socket *socket = Socket::Create(SOCKET_TCP);
        if (!socket)
        {
                printf("failed to create socket\n");
                return 0;
        }
        // bind the socket to a local port
        if (!socket->Bind("0.0.0.0", 8899))
        {
                printf("failed to bind socket\n");
                return 0;
        }
        if (!socket->Accept(0))
        {
                printf("failed to accept socket\n");
                return 0;
        }
        printf("server is running\n");
        if (cmdLine.GetFlag("help"))
                return usage();
        /*
         * attach signal handler
         */
        if (signal(SIGINT, sig_handler) == SIG_ERR)
                LogError("can't catch SIGINT\n");
        /*
         * create input stream
         */
        while (true)
        {
                // receive a message
                uint8_t buffer[1024];
                uint32_t remoteIP;
                uint16_t remotePort;
                size_t bytes = socket->Recieve(buffer, sizeof(buffer), &remoteIP, &remotePort);
                if (bytes == 0)
                {
                        printf("close client\n");
                        return 0;
                }
                else
                {
                        const char *receiveData = NULL;
                        printf("received message: %s\n", buffer);
                        cJSON *cjson_receive = cJSON_Parse((char *)buffer);
                        receiveData = cJSON_Print(cjson_receive);
                        printf("%s\n", receiveData);
                        SAFE_DELETE(receiveData);
                        // cJSON *fStickLat = cJSON_GetObjectItem(cjson_receive, "fStickLat");
                        // double m_fStickLat = cJSON_GetNumberValue(fStickLat);
                        // printf("%.10f\n", m_fStickLat);
                        // printf("m_fStickLat: %.10f\n", m_fStickLat);
                        cJSON *fpath = cJSON_GetObjectItem(cjson_receive, "fpath");
                        char *m_fpath = cJSON_GetStringValue(fpath);
                        printf("m_fpath: %s\n", m_fpath);
                        // 检测到 socket 等于 shutdown ,关闭 socket
                        if (strcmp((char *)buffer, "shutdown") == 0)
                        {
                                printf("shutting down\n");
                                break;
                        }
                        char av1[] = "detectnet";
                        char av2[] = "--network=ssd-mobilenet-v2";
                        char av3[] = "./socket_example/test1.jpg";
                        int len = strlen(m_fpath);
                        char av3_2[len];
                        strcpy(av3_2, m_fpath);
                        // char *fake_argv[3] = {av1, av2, m_fpath};
                        char *fake_argv[3] = {av1, av2, av3_2};
                        commandLine cmdLine(3, fake_argv);
                        printf("t1\n");
                        cJSON_Delete(cjson_receive);
                        // cJSON_Delete(fpath);
                        // SAFE_DELETE(m_fpath);
                        printf("t2\n");
                        /*
                         * create input stream
                         */
                        videoSource *input = videoSource::Create(cmdLine, ARG_POSITION(0));
                        if (!input)
                        {
                                LogError("detectnet:  failed to create input stream\n");
                                // return 1;
                                continue;
                        }
                        /*
                         * create output stream
                         */
                        videoOutput *output = videoOutput::Create(cmdLine, ARG_POSITION(1));
                        if (!output)
                        {
                                LogError("detectnet:  failed to create output stream\n");
                                // return 1;
                                continue;
                        }
                        /*
                         * processing loop
                         */
                        // while( !signal_recieved )
                        //{
                        //  capture next image
                        uchar3 *image = NULL;
                        int status = 0;
                        input->Capture(&image, &status);
                        // if (!input->Capture(&image, &status))
                        // {
                        //         // if( status == videoSource::TIMEOUT )
                        //         // continue;
                        //         // break; // EOS
                        // }
                        // detect objects in the frame
                        detectNet::Detection *detections = NULL;
                        const int numDetections = net->Detect(image, input->GetWidth(), input->GetHeight(), &detections, overlayFlags);
                        vector predObjList;
                        if (numDetections > 0)
                        {
                                LogVerbose("%i objects detected\n", numDetections);
                                for (int n = 0; n GetClassDesc(detections[n].ClassID), detections[n].Confidence);
                                        LogVerbose("bounding box %i  (%.2f, %.2f)  (%.2f, %.2f)  w=%.2f  h=%.2f\n", n, detections[n].Left, detections[n].Top, detections[n].Right, detections[n].Bottom, detections[n].Width(), detections[n].Height());
                                        if (detections[n].TrackID >= 0) // is this a tracked object?
                                                LogVerbose("tracking  ID %i  status=%i  frames=%i  lost=%i\n", detections[n].TrackID, detections[n].TrackStatus, detections[n].TrackFrames, detections[n].TrackLost);
                                        PredObj predObj;
                                        predObj.x1 = detections[n].Left;
                                        predObj.y1 = detections[n].Top;
                                        predObj.x2 = detections[n].Right;
                                        predObj.y2 = detections[n].Bottom;
                                        predObj.score = detections[n].Confidence;
                                        predObj.classID = detections[n].ClassID;
                                        predObj.width = detections[n].Width();
                                        predObj.height = detections[n].Height();
                                        predObj.classDesc = net->GetClassDesc(detections[n].ClassID);
                                        predObjList.push_back(predObj);
                                }
                        }
                        // predObjList to json
                        cJSON *cjson_send = cJSON_CreateObject();
                        cJSON *cjson_array = cJSON_CreateArray();
                        for (int i = 0; i Send((void *)json_str, strlen(json_str), remoteIP, remotePort))
                        {
                                // printf("failed to send message\n");
                                printf("client is disconnected\n");
                                break;
                        }
                        printf("t3\n");
                        //cJSON_Delete(cjson_send);
                        cJSON_Delete(cjson_array);
                        SAFE_DELETE(json_str);
                        // render outputs
                        if (false && output != NULL)
                        {
                                output->Render(image, input->GetWidth(), input->GetHeight());
                                // update the status bar
                                char str[256];
                                sprintf(str, "TensorRT %i.%i.%i | %s | Network %.0f FPS", NV_TENSORRT_MAJOR, NV_TENSORRT_MINOR, NV_TENSORRT_PATCH, precisionTypeToStr(net->GetPrecision()), net->GetNetworkFPS());
                                output->SetStatus(str);
                                // check if the user quit
                                // if( !output->IsStreaming() )
                                // break;
                        }
                        // print out timing info
                        net->PrintProfilerTimes();
                        printf("t4\n");
                        SAFE_DELETE(input);
                        SAFE_DELETE(output);
                        // SAFE_DELETE(image);
                        //}
                }
        }
        /*
         * destroy resources
         */
        LogVerbose("detectnet:  shutting down...\n");
        SAFE_DELETE(net);
        LogVerbose("detectnet:  shutdown complete.\n");
        return 0;
}
shuax   
你都知道你写的是 C++了,多用 RAII 自动释放啊,手动释放太难了。
YsHaNg   
TL;DR 扔给 GPT 了
Yes, there are several memory leaks in the provided code. Let's go through them:
1. In the loop where you receive messages via the socket, you allocate memory for `receiveData` using `cJSON_Print`, but you don't free it. You should free it after you're done using it.
2. Similarly, you create a `cJSON` object using `cJSON_Parse`, but you don't free it using `cJSON_Delete`.
3. You allocate memory for `json_str` using `cJSON_Print`, but you don't free it after sending it over the socket.
4. You allocate memory for `input` and `output` inside the loop, but you don't free them before the next iteration of the loop. This can lead to memory leaks if `input` or `output` fail to initialize.
To fix these memory leaks:
- Free `receiveData` after its use with `SAFE_DELETE(receiveData)`.
- Delete the `cjson_receive` object using `cJSON_Delete` after its use.
- Free `json_str` after sending it over the socket.
- Delete `input` and `output` objects at the end of each iteration of the loop before reinitializing them.
Here's how you can do it:
```cpp
SAFE_DELETE(receiveData);
cJSON_Delete(cjson_receive);
SAFE_DELETE(json_str);
SAFE_DELETE(input);
SAFE_DELETE(output);
```
Place these lines at appropriate locations in your code to ensure memory allocated dynamically is properly deallocated.
albert0yyyy
OP
  
@YsHaNg gpt 我问了,好像并不能解决.
有的指针释放了会报错提示已经释放过了,不能再次释放了。所以我就注释了一些会报错的释放操作
albert0yyyy
OP
  
@shuax 我去看看 RAII ,感谢
YsHaNg   
@albert0yyyy RAII+smart ptr 多用 auto 会让生活好很多
albert0yyyy
OP
  
@YsHaNg #5 感谢,我去看看。
watzds   
内存越用越多也正常啊,看能增加到多少
您需要登录后才可以回帖 登录 | 立即注册

返回顶部