new/delete和malloc/free的区别-zz

本文详细探讨了C++中new与malloc的区别,包括操作符与函数特性、内存管理方式及对象初始化过程。同时分析了new与malloc在内存分配上的不同之处,以及不当使用导致的问题。

1、new 是c++中的操作符,malloc是c 中的一个函数

2、new 不止是分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员的工作,同样free也不会调用析构函数

3、内存泄漏对于malloc或者new都可以检查出来的,区别在于new可以指明是那个文件的那一行,而malloc没有这些信息。

4、new 和 malloc效率比较

new可以认为是malloc加构造函数的执行。

new出来的指针是直接带类型信息的。

而malloc返回的都是void指针。

 

一:new delete 是运算符,malloc,free是函数

malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

我们先看一看malloc/free和new/delete如何实现对象的动态内存管理,见示例。


class Obj

{

public :

          Obj(void){ cout << “Initialization” << endl; }

~Obj(void){ cout << “Destroy” << endl; }

void      Initialize(void){ cout << “Initialization” << endl; }

void      Destroy(void){ cout << “Destroy” << endl; }

};


void UseMallocFree(void)

{

      Obj    *a = (obj *)malloc(sizeof(obj));     // 申请动态内存

      a->Initialize();                          // 初始化

      //…

      a->Destroy();     // 清除工作

      free(a);          // 释放内存

}


void UseNewDelete(void)

{

      Obj    *a = new Obj;    // 申请动态内存并且初始化

      //…

      delete a;             // 清除并且释放内存

}

示例用malloc/free和new/delete如何实现对象的动态内存管理

类Obj的函数Initialize模拟了构造函数的功能,函数Destroy模拟了析构函数的功能。函数UseMallocFree中,由于malloc/free不能执行构造函数与析构函数,必须调用成员函数Initialize和Destroy来完成初始化与清除工作。函数UseNewDelete则简单得多。

所以我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。

既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。

如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete必须配对使用,malloc/free也一样。

 

二:new delete在实现上其实调用了malloc,free函数。

 

三:new operator除了分配内存,还要调用构造函数。malloc函数只是负责分配内存。

 

简而言之:
new   是一个操作符,可以重载   
malloc是一个函数,可以覆盖   
new   初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数   
malloc仅仅分配内存,free仅仅回收内存  

 

 

 

 

 

问题:

我又一个对象类,里面有一个指针链表,动态分配空间,在析构的时候释放。开始对对象进行new操作,但是执行delete对象操作的时候出错,提示在析构的时候内存有问题。可是这时候成员一个比特的内存都没有分配啊。所以析构的时候应该什么内存操作都不执行。
更奇怪的是采用free()函数就可以释放这种对象,但是内存却不见减少,整个程序内存占用节节升高?这是为什么?

回复1:

你在析构函数当中没有正确的释放你申请的内存,比如,这个对象当中有一个指针,是采用动态申请内存的,在构造函数当中应该把它的值设置为NULL,然后在某个方法当中会申请内存,是采用new方法进行申请的,在析构函当中,应该先判断该指针是否为空,如果不为空,则使用delete释放内存,然后再把该指针设置为NULL。这样就可以了,如果你在外面是采用new申请这个对象,则在使用完成后使用delete释放就可以了。

回复2:

补充一点:new和malloc虽然都是申请内存,但申请的位置不同,new的内存从free store
分配,而malloc的内存从heap分配(详情请看ISO14882的内存管理部分),
free store和heap很相似,都是动态内存,但是位置不同,这就是为什么new
出来的内存不能通过free来释放的原因。不过微软编译器并没有很好的执行标准,
很有可能把free store和heap混淆了,因此,free有时也可以。再补充一点:delete时候不需要检查NULL

回复3:

呵,我也来凑合
如果TYPE *p = new TYPE[n]  那么就要 delete[] p

回复4:

malloc和free(及其变体)会产生问题的原因在于它们太简单:他们不知道构造函数和析构函数。

假设用两种方法给一个包含10个string对象的数组分配空间,一个用malloc,另一个用new:

  

string *stringarray1 =
static_cast<string*>(malloc(10 * sizeof(string)));

string *stringarray2 = new string[10];

其结果是,stringarray1确实指向的是可以容纳10个string对象的足够空间,但内存里并没有创建这些对象。而且,如果你不从这种晦涩的语法怪圈(详见条款m4和m8的描述)里跳出来的话,你没有办法来初始化数组里的对象。换句话说,stringarray1其实一点用也没有。相反,stringarray2指向的是一个包含10个完全构造好的string对象的数组,每个对象可以在任何读取string的操作里安全使用。

假设你想了个怪招对stringarray1数组里的对象进行了初始化,那么在你后面的程序里你一定会这么做:


free(stringarray1);
delete [] stringarray2;// 参见条款5:这里为什么要加上个"[]"

调用free将会释放stringarray1指向的内存,但内存里的string对象不会调用析构函数。如果string对象象一般情况那样,自己已经分配了内存,那这些内存将会全部丢失。相反,当对stringarray2调用delete时,数组里的每个对象都会在内存释放前调用析构函数。

既然new和delete可以这么有效地与构造函数和析构函数交互,选用它们是显然的。

把new和delete与malloc和free混在一起用也是个坏想法。对一个用new获取来的指针调用free,或者对一个用malloc获取来的指针调用delete,其后果是不可预测的。大家都知道“不可预测”的意思:它可能在开发阶段工作良好,在测试阶段工作良好,但也可能会最后在你最重要的客户的脸上爆炸。

new/delete和malloc/free的不兼容性常常会导致一些严重的复杂性问题。举个例子,<string.h>里通常有个strdup函数,它得到一个char*字符串然后返回其拷贝:


char * strdup(const char *ps); // 返回ps所指的拷贝
在有些地方,c和c++用的是同一个strdup版本,所以函数内部是用malloc分配内存。这样的话,一些不知情的c++程序员会在调用strdup后忽视了必须对strdup返回的指针进行free操作。为了防止这一情况,有些地方会专门为c++重写strdup,并在函数内部调用了new,这就要求其调用者记得最后用delete。你可以想象,这会导致多么严重的移植性问题,因为代码中strdup以不同的形式在不同的地方之间颠来倒去。

c++程序员和c程序员一样对代码重用十分感兴趣。大家都知道,有大量基于malloc和free写成的代码构成的c库都非常值得重用。在利用这些库时,最好是你不用负责去free掉由库自己malloc的内存,并且/或者,你不用去malloc库自己会free掉的内存,这样就太好了。其实,在c++程序里使用malloc和free没有错,只要保证用malloc得到的指针用free,或者用new得到的指针最后用delete来操作就可以了。千万别马虎地把new和free或malloc和delete混起来用,那只会自找麻烦。

既然malloc和free对构造函数和析构函数一无所知,把malloc/free和new/delete混起来用又象嘈杂拥挤的晚会那样难以控制,那么,你最好就什么时候都一心一意地使用new和delete吧。

回复5:

malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

回复6:

delete的时候可能需要释放多个指针的内存
free和delete的区别是
对于对象来说
free的确释放了对象的内存,但是不调用对象的析构函数,所以如果在对象中使用new分配的内存就会泄露
delete不仅释放对象的内存,并且调用对象的析构函数

 

#include <sys/termios.h> #include <mosquitto.h> #include <sys/wait.h> #include <sys/time.h> #include "signal.h" #include "rc.h" #include "mqtt.h" static struct list_head mqtt_upflow; static pthread_mutex_t upflow_mutex; //extern struct list_head mqtt_downflow; static struct mosquitto *mosq = NULL; static int publish_finished = 1; static int already_connected = 0; static int need_restart = 0; int g_mqtt_sigid[150]; int g_mqtt_data = 0; int mqtt_public_message_enqueue(char *data, char *topic, int qos) { struct pub_msg *msg; msg = (struct pub_msg *)malloc(sizeof(struct pub_msg)); if(msg == NULL) { return 0; } memset(msg, 0, sizeof(struct pub_msg)); snprintf(msg->data, sizeof(msg->data), "%s", data); snprintf(msg->topic, sizeof(msg->topic), "%s", topic); msg->qos = qos; msg->mid = -1; pthread_mutex_lock(&upflow_mutex); list_add_tail(&msg->list, &mqtt_upflow); pthread_mutex_unlock(&upflow_mutex); return 1; } /* *why need this function? *when mqtt process exit, always has one mqtt thread not exit , so case mqtt process can not restart *add by jerry, 22-06-21 * * */ static void mqtt_exit(void) { int ret; /* *ret != -1 *WIFEXITED(ret) is true *0 == WEXITSTATUS(ret) *all above success, system function is success, other is failed * */ do { ret = system("killall -9 mqtt"); }while(!((ret != -1) && (WIFEXITED(ret)) && (0 == WEXITSTATUS(ret)))); } static void mqtt_sig_handler(int sig) { switch (sig) { case SIGTERM: case SIGKILL: case SIGINT: syslog(LOG_NOTICE, "Got a signal! exit!!"); mqtt_exit(); break; case SIGHUP: syslog(LOG_NOTICE, "Got a signal! exit!!"); mqtt_exit(); break; case SIGUSR1: break; case SIGUSR2: break; } } static void mqtt_deamon() { struct sigaction sa; FILE *fp; if ( fork() !=0 ) exit(0); openlog("mqtt", LOG_PID, LOG_USER); sa.sa_handler = mqtt_sig_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGUSR1, &sa, NULL); sigaction(SIGUSR2, &sa, NULL); sigaction(SIGHUP, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGKILL, &sa, NULL); sigaction(SIGINT, &sa, NULL); signal(SIGCHLD, chld_reap); if ( setsid() < 0 ) exit(1); if ( chdir("/") == -1 ) exit(1); kill_pidfile_tk(MQTT_PID_FILE); if ((fp = fopen(MQTT_PID_FILE, "w")) != NULL) { fprintf(fp, "%d", getpid()); fclose(fp); } } /* Callback called when the client receives a CONNACK message from the broker. */ static void on_connect(struct mosquitto *mosq, void *obj, int reason_code) { // int rc; // char sub_topic[256] = {0}; /* Print out the connection result. mosquitto_connack_string() produces an * appropriate string for MQTT v3.x clients, the equivalent for MQTT v5.0 * clients is mosquitto_reason_string(). */ syslog(LOG_ERR, "on_connect: %s", mosquitto_connack_string(reason_code)); if(reason_code != 0){ /* If the connection fails for any reason, we don't want to keep on * retrying in this example, so disconnect. Without this, the client * will attempt to reconnect. */ mosquitto_disconnect(mosq); } else { already_connected = 1; //subscribe when mqtt connect success #if 0 /* Making subscriptions in the on_connect() callback means that if the * connection drops and is automatically resumed by the client, then the * subscriptions will be recreated when the client reconnects. */ snprintf(sub_topic, sizeof(sub_topic), "VirtualTopic/mqtt/command/%s", nvram_safe_get("iot_sendorid")); syslog(LOG_INFO, "sub topic: %s", sub_topic); rc = mosquitto_subscribe(mosq, NULL, sub_topic, 0); if(rc != MOSQ_ERR_SUCCESS){ syslog(LOG_ERR, "Error subscribing: %s\n", mosquitto_strerror(rc)); /* We might as well disconnect if we were unable to subscribe */ mosquitto_disconnect(mosq); } #endif } } /* Callback called when the broker sends a SUBACK in response to a SUBSCRIBE. */ static void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos) { int i; bool have_subscription = false; /* In this example we only subscribe to a single topic at once, but a * SUBSCRIBE can contain many topics at once, so this is one way to check * them all. */ for(i=0; i<qos_count; i++){ syslog(LOG_ERR, "on_subscribe: %d:granted qos = %d", i, granted_qos[i]); if(granted_qos[i] <= 2){ have_subscription = true; } } if(have_subscription == false){ /* The broker rejected all of our subscriptions, we know we only sent * the one SUBSCRIBE, so there is no point remaining connected. */ syslog(LOG_ERR, "Error: All subscriptions rejected."); mosquitto_disconnect(mosq); } } /* Callback called when the client knows to the best of its abilities that a * PUBLISH has been successfully sent. For QoS 0 this means the message has * been completely written to the operating system. For QoS 1 this means we * have received a PUBACK from the broker. For QoS 2 this means we have * received a PUBCOMP from the broker. */ static void on_publish(struct mosquitto *mosq, void *obj, int mid) { struct list_head *pos = NULL; struct pub_msg *msg = NULL; syslog(LOG_ERR, "Message with mid %d has been published.", mid); //when qos is 1 or 2, message publish success, delete message from queue here pthread_mutex_lock(&upflow_mutex); list_for_next_each(pos, &mqtt_upflow) { msg = container_of(pos,struct pub_msg,list); if(msg->mid == mid) { //syslog(LOG_INFO,"2content:%s, topic:%s, qos:%d, mid:%d", msg->data, msg->topic, msg->qos, msg->mid); list_del(&msg->list); free(msg); publish_finished = 1; break; } } pthread_mutex_unlock(&upflow_mutex); } /* Callback called when the client receives a message. */ static void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg) { syslog(LOG_INFO, "-----on message"); mqtt_public_message_enqueue("hello", "mqtt1", 0); } char *get_time_str(int type, char *buf, int blen) { struct tm *info; struct timeval tv; struct timezone tz; if(buf == NULL) { return NULL; } gettimeofday(&tv, &tz); info = localtime(&tv.tv_sec); if(type == 0) { snprintf(buf, blen, "%d-%.2d-%.2d %.2d:%.2d:%.2d.%ld", 1900 + info->tm_year, info->tm_mon + 1, info->tm_mday, info->tm_hour, info->tm_min, info->tm_sec, tv.tv_usec/1000); } else if(type = 1) { snprintf(buf, blen, "%d%.2d%.2d%.2d%.2d%.2d", 1900 + info->tm_year, info->tm_mon + 1, info->tm_mday, info->tm_hour, info->tm_min, info->tm_sec); } return buf; } char *printf_time_sub(char sub, uint8_t count, char *out) { time_t current_time; struct tm * timeinfo; time(&current_time); timeinfo = localtime(&current_time); switch (sub) { case 'Y': if (count == 4) sprintf(out, "%d", timeinfo->tm_year + 1900); else sprintf(out, "%d", timeinfo->tm_year + 1900 - 2000); break; case 'M': if (count == 2) sprintf(out, "%02d", timeinfo->tm_mon + 1); else sprintf(out, "%d", timeinfo->tm_mon + 1); break; case 'D': if (count == 2) sprintf(out, "%02d", timeinfo->tm_mday); else sprintf(out, "%d", timeinfo->tm_mday); break; case 'h': if (count == 2) sprintf(out, "%02d", timeinfo->tm_hour); else sprintf(out, "%d", timeinfo->tm_hour); break; case 'm': if (count == 2) sprintf(out, "%02d", timeinfo->tm_min); else sprintf(out, "%d", timeinfo->tm_min); break; case 's': if (count == 2) sprintf(out, "%02d", timeinfo->tm_sec); else sprintf(out, "%d", timeinfo->tm_sec); break; default: break; } return (out + strlen(out)); } uint16_t get_length(char *line) { uint16_t len = 0; while ( *line) { if (*line == '\n') { if (len) len++; break; } else { len++; line++; } } return len; } char *printf_intf_data(char *line) { uint16_t line_len = get_length(line); uint16_t pos = 0; char *result = strstr(line, "<<"); if(NULL == result) { return; } pos = result - line; line += pos; line_len -= pos; result = strstr(line, "INTF"); if(NULL == result) { return; } pos = result - line; char temp_pos[6] = {0}; snprintf(temp_pos, sizeof(temp_pos), "%d", pos); nvram_set("intf_pos", temp_pos); line += (pos + 4); line_len -= (pos + 4); char intf_data[6] = {0}; int i = 0; char temp[32] = {0}; char temp_val[32] = {0}; char mqtt_data[32] = {0}; char buf[6] = {0}; while(*line != ')') { if(*line == '(') { line ++; continue; } intf_data[i] = *line; i ++; line ++; } int j; for(j = 0; j <= nvram_get_int("g_reg_num"); j++) { memset(temp, 0, sizeof(temp)); memset(temp_val, 0, sizeof(temp_val)); memset(mqtt_data, 0, sizeof(mqtt_data)); snprintf(temp, sizeof(temp), "regAddr_%d", j+1); if(!strlen(nvram_safe_get(temp))) { sleep(1); } if(nvram_get_int(temp) == atoi(intf_data)) { snprintf(temp_val, sizeof(temp_val), "signalval_%d", j+1); snprintf(mqtt_data, sizeof(mqtt_data), "mqtt_report_data%d", g_mqtt_data); nvram_set(mqtt_data, nvram_safe_get(temp_val)); g_mqtt_data ++; snprintf(buf, sizeof(buf), "%d", g_mqtt_data); nvram_set("g_mqtt_data", buf); } } return; } char *printf_time(char *line) { /* "time":"%s"<<TIME(YYYY-MM-DD hh:mm:ss.SSSzz) YYYY年 MM月 DD日 hh时 mm分 ss秒 SSS毫秒 zz +-08 zzzz +-08:00 */ uint16_t line_len = get_length(line); uint16_t pos = 0; char *result = strstr(line, "<<"); pos = result - line; line += pos; line_len -= pos; //定位TIME result = strstr(line, "TIME"); pos = result - line; char temp_pos[6] = {0}; snprintf(temp_pos, sizeof(temp_pos), "%d", pos); nvram_set("time_pos", temp_pos); line += (pos + 4); line_len -= (pos + 4); char field[5]; uint8_t start = 0; char *timestr = (char *)malloc(50); //memset(timestr, ' ', 50); // 初始化内存空间 char *temp = timestr; do { switch (*line) { case 'Y': case 'M': case 'D': case 'h': case 'm': case 's': case 'S': case 'z': switch (start) { case 0: field[start++] = *line; break; case 4: start = 0; continue; default: if (*line == field[start - 1]) field[start++] = *line; else { timestr = printf_time_sub(field[0], start, timestr); start = 0; continue; } } break; case '(': break; case ')': if (start) { timestr = printf_time_sub(field[0], start, timestr); start = 0; } else { *timestr = 0; } nvram_set("mqtt_time", temp); return temp; default: if (start) { timestr = printf_time_sub(field[0], start, timestr); start = 0; *timestr++ = *line; } else *timestr++ = *line; break; } line++; } while (*line); if (temp == timestr) { free(timestr); return NULL; } else return temp; } char *encode_mqtt_pack() { char *line = NULL; char line_temp[2000] = {0}; line = nvram_safe_get("mqtt_template"); //line_temp = line; char report_packet_string[1000] = {0}; syslog(LOG_INFO, "========================%s", line); snprintf(line_temp, sizeof(line_temp),"%s", line); char *result = strstr(line_temp, "\":"); while(nvram_get_int("g_modbus_start") == 1) { sleep(1); syslog(LOG_INFO, "{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{wait for modbus}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}"); continue; } // g_mqtt_start = 1; nvram_set("g_mqtt_start", "1"); sleep(1); while(result != NULL) { if(nvram_get_int("g_reg_num") != nvram_get_int("g_mqtt_flag")) { sleep(1); } printf_intf_data(result); result = strstr(result + strlen("\":"), "\":"); } int i = 0; char mqtt_data[32] = {0}; printf_time(line); float num[50] = {0}; for(i = 0; i < nvram_get_int("g_mqtt_data"); i ++) { memset(mqtt_data, 0, sizeof(mqtt_data)); snprintf(mqtt_data, sizeof(mqtt_data), "mqtt_report_data%d", i); sscanf(nvram_safe_get(mqtt_data), "%f", &num[i]); //syslog(LOG_INFO, "======================num%d :%f", i, num[i]); } if(num[nvram_get_int("g_reg_num")] == 0) { syslog(LOG_INFO, "num[%d] = 0", nvram_get_int("g_reg_num")); return NULL; } // char tmp_buf[10] = {0}; // snprintf(tmp_buf, sizeof(tmp_buf), ) // if(nvram_get_int("intf_pos") < nvram_get_int("time_pos")) //将intftime值赋值给模板 char *tmp_line = line; char tmp_string[70] = {0}; char packet_string[80] = {0}; char add_n_string[90] = {0}; i = 0; int m = 0; int data_num = 0; while(tmp_line[m]) { if(tmp_line[m] == '\n') { if(NULL != strstr(tmp_string, "INTF")) { sprintf(packet_string, tmp_string, num[data_num]); data_num ++; sprintf(add_n_string, "%s\n", packet_string); memset(tmp_string, 0, sizeof(tmp_string)); } else if(NULL != strstr(tmp_string, "TIME")) { sprintf(packet_string, tmp_string, nvram_safe_get("mqtt_time")); sprintf(add_n_string, "%s\n", packet_string); memset(tmp_string, 0, sizeof(tmp_string)); } else { sprintf(packet_string, "%s", tmp_string); sprintf(add_n_string, "%s\n", packet_string); memset(tmp_string, 0, sizeof(tmp_string)); } strcat(report_packet_string, add_n_string); m ++; i = 0; } tmp_string[i] = tmp_line[m]; i++; m++; } strcat(report_packet_string, tmp_string); char *token = report_packet_string; char report_mqtt_string[1000] = {0}; int k = 0; while(*token != NULL) { if(*token != ',') { report_mqtt_string[k] = *token; k ++; token ++; } else { report_mqtt_string[k] = *token; k ++; token ++; report_mqtt_string[k] = '\n'; k ++; while(*token != '\n') { token ++; } token ++; } } if(NULL == strstr(report_mqtt_string, "{") || NULL == strstr(report_mqtt_string, "}")) { return NULL; } return report_mqtt_string; } static void *formate_data_thread(void *arg) { char *buf = NULL; while(1) { buf = encode_mqtt_pack(); syslog(LOG_INFO, "======================buf :%s", buf); if(buf == NULL) { sleep(3); continue; } // snprintf(buf, sizeof(buf), "hello world%d", count); mqtt_public_message_enqueue(buf, nvram_safe_get("iot_topic"), 0); sleep(nvram_get_int("iot_mqtt_interval")); } } static void *publish_thread(void *arg) { int rc; struct list_head *pos; struct pub_msg *msg = NULL; while(1) { if((publish_finished) == 0 || (already_connected == 0)) { //syslog(LOG_ERR, "Mqtt not connected or message is null"); sleep(1); if(need_restart == 1) { mosquitto_disconnect(mosq); } continue; } pthread_mutex_lock(&upflow_mutex); list_for_next_each(pos, &mqtt_upflow) { msg = container_of(pos,struct pub_msg,list); break; } pthread_mutex_unlock(&upflow_mutex); //mqtt_upflow is not null if(pos != &mqtt_upflow) { publish_finished = 0; //syslog(LOG_INFO,"1content:%s, topic:%s, qos:%d, mid:%d", msg->data, msg->topic, msg->qos, msg->mid); rc = mosquitto_publish(mosq, &msg->mid, msg->topic, strlen(msg->data), msg->data, msg->qos, false); g_mqtt_data = 0; if(rc != MOSQ_ERR_SUCCESS) { publish_finished = 1; syslog(LOG_ERR, "Error publishing: %s", mosquitto_strerror(rc)); sleep(1); } nvram_set("g_mqtt_start", "0"); } else { //syslog(LOG_ERR, "current msg is NULL"); sleep(1); if(need_restart == 1) { mosquitto_disconnect(mosq); } } } } static void mqtt_tls_config(void) { char buf[64]; FILE *fp = NULL; int rc = 0; mkdir("/etc/mqtt",0755); snprintf(buf, sizeof(buf), "/etc/mqtt/ca.crt"); fp = fopen(buf,"wb"); if(fp != NULL) { chmod(buf,S_IRUSR|S_IWUSR); fprintf(fp,"%s",nvram_safe_get("iot_root_ca")); fclose(fp); } if(nvram_match("iot_mutual_enable", "1")) { snprintf(buf, sizeof(buf), "/etc/mqtt/client.crt"); fp = fopen(buf,"wb"); if(fp != NULL) { chmod(buf,S_IRUSR|S_IWUSR); fprintf(fp,"%s",nvram_safe_get("iot_client_ca")); fclose(fp); } snprintf(buf, sizeof(buf), "/etc/mqtt/client.key"); fp = fopen(buf,"wb"); if(fp != NULL) { chmod(buf,S_IRUSR|S_IWUSR); fprintf(fp,"%s",nvram_safe_get("iot_client_key")); fclose(fp); } rc = mosquitto_tls_set(mosq, "/etc/mqtt/ca.crt", "/etc/mqtt", "/etc/mqtt/client.crt", "/etc/mqtt/client.key", NULL); if(rc != MOSQ_ERR_SUCCESS) { syslog(LOG_ERR, "Error: set tls %s\n", mosquitto_strerror(rc)); } } else { rc = mosquitto_tls_set(mosq, "/etc/mqtt/ca.crt", NULL, NULL, NULL, NULL); if(rc != MOSQ_ERR_SUCCESS) { syslog(LOG_ERR, "Error: set tls %s\n", mosquitto_strerror(rc)); } } } int mqtt_main(int argc, char *argv[]) { int rc; pthread_t publish_pid, formate_pid, modbus_pid; char *username = NULL, *passwd = NULL; //char will_buf[1024] = {0}; nvram_set("g_mqtt_start", "0"); nvram_set("g_modbus_start", "1"); mqtt_deamon(); if (!strcmp(nvram_safe_get("mqtt_enable_rtu"), "0")) { syslog( LOG_NOTICE, "MQTT Disabled, Pause!!" ); while (1) { pause(); } } //check ppp online while( !check_wanup() ) { syslog(LOG_NOTICE, "MQTT : Cellular Offline" ); sleep( 3 ); } //等待modbus进程读取数据 sleep(10); /* Required before calling other mosquitto functions */ mosquitto_lib_init(); INIT_LIST_HEAD(&mqtt_upflow); pthread_mutex_init(&upflow_mutex, NULL); /* Create a new client instance. * id = NULL -> ask the broker to generate a client id for us * clean session = true -> the broker should remove old sessions when we connect * obj = NULL -> we aren't passing any of our private data for callbacks */ mosq = mosquitto_new(nvram_match("iot_clientid", "") ? NULL : nvram_safe_get("iot_clientid"), true, NULL); if(mosq == NULL) { syslog(LOG_ERR, "Error: Out of memory."); return 0; } mqtt_tls_config(); //downflow data //INIT_LIST_HEAD(&mqtt_downflow); //mqtt will message set //mosquitto_will_set(mosq, MQTT_PUBLISH_TOPIC, strlen(will_buf), will_buf, 1, false); username = nvram_safe_get("iot_username"); passwd = nvram_safe_get("iot_passwd"); if(strlen(username) == 0) { username = NULL; } if(strlen(passwd) == 0) { passwd = NULL; } rc = mosquitto_username_pw_set(mosq, username, passwd); if(rc != MOSQ_ERR_SUCCESS) { syslog(LOG_ERR, "Error1: %s", mosquitto_strerror(rc)); goto ERROR; } /* Configure callbacks. This should be done before connecting ideally. */ mosquitto_connect_callback_set(mosq, on_connect); mosquitto_publish_callback_set(mosq, on_publish); //mosquitto_subscribe_callback_set(mosq, on_subscribe); mosquitto_message_callback_set(mosq, on_message); /* Connect to test.mosquitto.org on port 1883, with a keepalive of 60 seconds. * This call makes the socket connection only, it does not complete the MQTT * CONNECT/CONNACK flow, you should use mosquitto_loop_start() or * mosquitto_loop_forever() for processing net traffic. */ rc = mosquitto_connect(mosq, nvram_safe_get("iot_hostname"), nvram_get_int("iot_port"), 60); if(rc != MOSQ_ERR_SUCCESS){ syslog(LOG_ERR, "Error connect: %s", mosquitto_strerror(rc)); goto ERROR; } if (pthread_create(&publish_pid, NULL, (void *)publish_thread, NULL) != 0) { syslog(LOG_NOTICE, "MQTT Thread %d ERR",(int) publish_pid); goto ERROR; } else { pthread_detach(publish_pid); } #if 1 if (pthread_create(&formate_pid, NULL, (void *)formate_data_thread, NULL) != 0) { syslog(LOG_NOTICE, "MQTT formate Thread %d ERR",(int) formate_pid); goto ERROR; } else { pthread_detach(formate_pid); } #endif // if (pthread_create(&modbus_pid, NULL, (void *)modbus_process_thread, NULL) != 0) // { // syslog(LOG_NOTICE, "MQTT modbus Thread %d ERR",(int) modbus_pid); // goto ERROR; // } // else // { // pthread_detach(modbus_pid); // } /* Run the network loop in a blocking call. The only thing we do in this * example is to print incoming messages, so a blocking call here is fine. * * This call will continue forever, carrying automatic reconnections if * necessary, until the user calls mosquitto_disconnect(). */ //mosquitto_loop_forever(mosq, 60*1000, 1);//keeplive 60 second do{ rc = mosquitto_loop(mosq, 50, 1); }while(rc == MOSQ_ERR_SUCCESS); syslog(LOG_ERR, "End Error: %s", mosquitto_strerror(rc)); ERROR: pthread_mutex_destroy(&upflow_mutex); mosquitto_loop_stop(mosq, false); mosquitto_destroy(mosq); mosquitto_lib_cleanup(); mqtt_exit(); return 0; } 使用上述代码有了更详细的错误日志TLS Error in mosquitto_connect: A TLS error occurred. (code: 8);TLS Error: Generic TLS connection error;Check certificate paths, permissions, and validity;Failed to connect to MQTT broker for device 3: A TLS error occurred.请根据错误日志分析原因并解决
10-15
基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现扩展应用。; 适合人群:具备电力系统基础知识Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值