ArduinoJson parsing fail when reading string from EEPROM - c++

Before someone flags this as duplicate I have found these two links and neither totally apply although I have implemented at least a little of both.
Buffer gets overwritten
Arduino reading json from EEPROM / converting uint8_t to char
My problem is this. I am trying to read and write a JSON string to an Arduinos EEPROM using ArduinoJson library (https://github.com/bblanchon/ArduinoJson). In the below code I generate a JsonObject from a hard coded JSON string (this works). I then write it to EEPROM (this works). It then gets read back from EEPROM (this works) but when I try and parse the second string using ArduinoJSON i get a parse failure.
For the purpose of testing I also clear the EEPROM each time just in case although eventually this will be removed.
The code compiles with no errors. I am hoping that someone more knowledgable in C++ than myself will spot something really obvious. I am compiling this onto a NodeMCU (esp8266).
#include <ArduinoJson.h>
#include <EEPROM.h>
StaticJsonBuffer<400> jsonBuffer;
JsonObject *jsonObject;
JsonObject *config;
String dummyJson = "{\"name\":\"RGB LED 1\",\"io\":[\"pwm1\",\"pwm2\",\"pwm3\"],\"io_type\":\"output\",\"device\":\"pwm_output\",\"uuid\":\"5a81f424aaf8d1e951ae78d270668337\",\"ip\":\"255.255.255.255\"}";
void setup()
{
Serial.begin(9600);
while (!Serial)
{
continue;
}
EEPROM.begin(512);
Serial.println("\n\n");
clearEEPROM();
createDummyJsonObject();
writeJsonToEEPROM();
readJsonFromEEPROM();
}
void createDummyJsonObject()
{
jsonObject = &jsonBuffer.parseObject(dummyJson);
if (!jsonObject->success())
{
Serial.println("jsonBuffer.parseObject() failed");
return;
}
else
{
Serial.println("JSON object generated from dummy string");
jsonObject->prettyPrintTo(Serial);
Serial.println("\n\n");
}
}
void loop()
{
// not used
}
void clearEEPROM()
{
for (int i = 0; i < 512 + 1; i++)
{
EEPROM.write(i, 0);
}
EEPROM.commit();
}
void writeJsonToEEPROM()
{
String jsonStr;
jsonObject->printTo(jsonStr);
for (int i = 0; i < jsonStr.length(); ++i)
{
EEPROM.write(i, jsonStr[i]);
}
EEPROM.write(jsonStr.length(), byte(0));
EEPROM.commit();
}
void readJsonFromEEPROM()
{
String jsonStr;
for (int i = 0; i < 512; ++i)
{
char c = char(EEPROM.read(i));
if (c != 0)
{
jsonStr += c;
delay(1);
}
else
{
break;
}
}
Serial.println(jsonStr);
char charBuf[jsonStr.length()];
jsonStr.toCharArray(charBuf, jsonStr.length());
config = &jsonBuffer.parseObject(charBuf);
if (!config->success())
{
Serial.println("jsonObject.parseObject() failed ");
return;
}
else
{
// Never reaches this point!
Serial.println("\nJSON object generated from EEPROM data");
config->prettyPrintTo(Serial);
Serial.println("\n\n");
}
}

The size allocated for charBuf should be jsonStr.length() + 1 because you need space for a string terminator. Therefore you should also add something like charBuf[jsonStr.length()] = '\0'; to provide that string terminator:
int const jsonStringLengh = jsonStr.length();
char charBuf[jsonStringLengh + 1];
jsonStr.toCharArray(charBuf, jsonStringLengh);
charBuf[jsonStringLengh] = '\0';

Ok so this solved it. All I had to do was create a new StaticJsonBuffer for the second string parse. For anyone who is having a similar issue here's the working code.
#include <ArduinoJson.h>
#include <EEPROM.h>
StaticJsonBuffer<512> jsonBuffer;
JsonObject *jsonObject;
JsonObject *config;
String dummyJson = "{\"name\":\"RGB LED 1\",\"io\":[\"pwm1\",\"pwm2\",\"pwm3\"],\"io_type\":\"output\",\"device\":\"pwm_output\",\"uuid\":\"5a81f424aaf8d1e951ae78d270668337\",\"ip\":\"255.255.255.255\"}";
void setup()
{
Serial.begin(9600);
while (!Serial)
{
continue;
}
EEPROM.begin(512);
clearEEPROM();
createDummyJsonObject();
writeJsonToEEPROM();
readJsonFromEEPROM();
}
void createDummyJsonObject()
{
jsonObject = &jsonBuffer.parseObject(dummyJson);
if (!jsonObject->success())
{
Serial.println("jsonBuffer.parseObject() failed");
return;
}
else
{
Serial.println("JSON object generated from dummy string");
}
}
void loop()
{
// not used
}
void clearEEPROM()
{
for (int i = 0; i < 512 + 1; i++)
{
EEPROM.write(i, 0);
}
EEPROM.commit();
}
void writeJsonToEEPROM()
{
String jsonStr;
jsonObject->printTo(jsonStr);
for (int i = 0; i < jsonStr.length(); ++i)
{
EEPROM.write(i, jsonStr[i]);
}
EEPROM.write(jsonStr.length(), byte(0));
EEPROM.commit();
}
void readJsonFromEEPROM()
{
String jsonStr;
for (int i = 0; i < 512; ++i)
{
char c = char(EEPROM.read(i));
if (c != 0)
{
jsonStr += c;
delay(1);
}
else
{
break;
}
}
StaticJsonBuffer<512> jsonBuffer2;
config = &jsonBuffer2.parseObject(jsonStr);
if (!config->success())
{
Serial.println("jsonObject.parseObject() failed ");
return;
}
else
{
Serial.println("\nJSON object generated from EEPROM data");
config->prettyPrintTo(Serial);
Serial.println("\n\n");
}
}

Related

Arduino compiler failing with error code - invalid types 'int[int]' for array subscript

Quite a bit of untested code but the only thing really concerning me at the moment is my DISPLAY variable. I don't see how it is much different than my FONT array (which works fine) yet DISPLAY is the one that gets 'invalid types 'int[int]' for array subscript' I should be able to index an array of integers with integers (at least I have been with FONT).
#include <WiFiNINA.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "font.h"
const int PIXEL_WIDTH = 30;
const int PIXEL_HEIGHT = 5;
int DISPLAY[PIXEL_HEIGHT][PIXEL_WIDTH] = {};
bool MILI_TIME = false;
String FORMATTING[2] = {"LONGS","SHORTH:LONGM"};
char ssid[] = "REMOVED"; // your network SSID (name) between the " "
char pass[] = "REMOVED"; // your network password between the " "
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS; // connection status
WiFiServer server(80); // server socket
WiFiClient client = server.available();
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
int ledPin = LED_BUILTIN;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
while (!Serial); // dont do anything until there is a serial connection
enable_WiFi();
connect_WiFi();
server.begin();
printWifiStatus();
timeClient.begin();
timeClient.setTimeOffset(-14400);
}
void loop() {
timeClient.update();
client = server.available();
if (client) {
printWEB();
}
preRender();
}
void preRender(){
String FILLED_FORMATTING[2] = FORMATTING;
for(int i=0;i<2;i++){
FILLED_FORMATTING[i].replace("LONGH",leadWithZero(timeHours()));
FILLED_FORMATTING[i].replace("LONGM",leadWithZero(timeMinutes()));
FILLED_FORMATTING[i].replace("LONGS",leadWithZero(timeSeconds()));
FILLED_FORMATTING[i].replace("SHORTH",timeHours());
FILLED_FORMATTING[i].replace("SHORTM",timeMinutes());
FILLED_FORMATTING[i].replace("SHORTS",timeSeconds());
}
int x = 0;
for(int i=0;i<FILLED_FORMATTING[0].length();i++){
int c_ID = charID(FILLED_FORMATTING[0][i]);
if(c_ID < 38){
for(int j=0;j<5;j++){
DISPLAY[j][x] = FONT[c_ID][j][0];
x += 1;
DISPLAY[j][x] = FONT[c_ID][j][1];
x += 1;
DISPLAY[j][x] = FONT[c_ID][j][2];
x += 1;
if(i != FILLED_FORMATTING[0].length()){
DISPLAY[j][x] = 0;
x += 1;
}
}
}
}
x = PIXEL_WIDTH-1;
for(int i=FILLED_FORMATTING[1].length()-1;i>=0;i--){
int c_ID = charID(FILLED_FORMATTING[1][i]);
if(c_ID < 38){
for(int j=0;j<5;j++){
DISPLAY[j][x] = FONT[c_ID][j][0];
x -= 1;
DISPLAY[j][x] = FONT[c_ID][j][1];
x -= 1;
DISPLAY[j][x] = FONT[c_ID][j][2];
x -= 1;
if(i != 0){
DISPLAY[j][x] = 0; //<----------- compiler error here, and ofc all instances above
x -= 1;
}
}
}
}
}
int charID(char c){
for(int i=0;i<FONT_ID.length();i++){
if(FONT_ID[i] == c){
return i;
}
}
return 40;
}
String timeHours(){
if(MILI_TIME){
return String(timeClient.getHours());
}
else{
return convFromMili(timeClient.getHours());
}
}
String timeMinutes(){
return String(timeClient.getMinutes());
}
String timeSeconds(){
return String(timeClient.getSeconds());
}
String leadWithZero(String t){
if(t.length() < 2){
t = "0"+t;
return t;
}
}
String convFromMili(int t){
if(t > 12){
t -= 12;
}else if(t == 0){
t += 12;
}
String ts = String(t);
return ts;
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
Serial.print("To see this page in action, open a browser to http://");
Serial.println(ip);
}
void enable_WiFi() {
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < "1.0.0") {
Serial.println("Please upgrade the firmware");
}
}
void connect_WiFi() {
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(10000);
}
}
void printWEB() {
if (client) { // if you get a client,
Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
//create the buttons
client.print(WiFi.getTime());
client.print("<br>");
client.print(timeClient.getEpochTime());
client.print("<br>");
client.print(timeClient.getFormattedTime());
client.print("<br>");
client.print(timeClient.getDay());
client.print("<br>");
client.print(timeClient.getHours());
client.print("<br>");
client.print(timeClient.getMinutes());
client.print("<br>");
client.print(timeClient.getSeconds());
client.print("<br>");
client.print("<div style=\"display:block;padding-left:calc(50% - 150px);margin-bottom:50px\"><div style=\"background-color:#e3e3e3;width:300px;height:120px;font-size:50px;text-align:center;padding-top:50px\">ON</div></div>");
client.print("<div style=\"display:block;padding-left:calc(50% - 150px)\"><div style=\"background-color:#e3e3e3;width:300px;height:120px;font-size:50px;text-align:center;padding-top:50px\">OFF</div></div>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
}
else { // if you got a newline, then clear currentLine:
currentLine = "";
}
}
else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
if (currentLine.endsWith("GET /H")) {
digitalWrite(ledPin, HIGH);
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(ledPin, LOW);
}
if (currentLine.endsWith("%VAL")) {
// Trim 'GET /' and '%VAL'
currentLine.remove(0,5);
currentLine.remove(currentLine.indexOf("%"),4);
Serial.println(currentLine);
Serial.println();
}
}
}
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
font.h:
int FONT[37][5][3] = {{{1,1,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,1,0},{0,1,0},{0,1,0},{0,1,0},{1,1,1},},{{1,1,1},{0,0,1},{1,1,1},{1,0,0},{1,1,1},},{{1,1,1},{0,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,1},{0,0,1},{0,0,1},},{{1,1,1},{1,0,0},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{1,0,0},{1,1,1},{1,0,1},{1,1,1},},{{1,1,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,1},{1,0,1},},{{1,1,0},{1,0,1},{1,1,0},{1,0,1},{1,1,0},},{{1,1,1},{1,0,0},{1,0,0},{1,0,0},{1,1,1},},{{1,1,0},{1,0,1},{1,0,1},{1,0,1},{1,1,0},},{{1,1,1},{1,0,0},{1,1,1},{1,0,0},{1,1,1},},{{1,1,1},{1,0,0},{1,1,1},{1,0,0},{1,0,0},},{{1,1,1},{1,0,0},{1,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,1},{1,0,1},{1,0,1},},{{1,1,1},{0,1,0},{0,1,0},{0,1,0},{1,1,1},},{{0,0,1},{0,0,1},{0,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,0},{1,0,1},{1,0,1},},{{1,0,0},{1,0,0},{1,0,0},{1,0,0},{1,1,1},},{{1,1,1},{1,1,1},{1,0,1},{1,0,1},{1,0,1},},{{1,1,0},{1,0,1},{1,0,1},{1,0,1},{1,0,1},},{{1,1,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,0},{1,0,0},},{{1,1,1},{1,0,1},{1,0,1},{1,1,0},{0,0,1},},{{1,1,1},{1,0,1},{1,1,0},{1,0,1},{1,0,1},},{{0,1,1},{1,0,0},{0,1,0},{0,0,1},{1,1,0},},{{1,1,1},{0,1,0},{0,1,0},{0,1,0},{0,1,0},},{{1,0,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,0,1},{0,1,0},{0,1,0},},{{1,0,1},{1,0,1},{1,0,1},{1,1,1},{1,1,1},},{{1,0,1},{1,0,1},{0,1,0},{1,0,1},{1,0,1},},{{1,0,1},{1,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{0,0,1},{0,1,0},{1,0,0},{1,1,1},},{{0,0,0},{0,1,0},{0,0,0},{0,1,0},{0,0,0}}};
String FONT_ID = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ:";
did check -
int D[5][30];
void setup() {
}
void loop() {
D[0][0] = 0;
}
and of course its fine, so I'm just wondering where I went wrong in the mess above?
and yes there's a good bit of mess/debugging stuff
Simple solution... don't use DISPLAY as a variable it seems. Changing to DISPLAY_ fixed it, figured the variable was defined as a normal integer somewhere... just not in my code.

ESP32 reboots unexpected - problematic variable?

I have a problem with (at least) one row in my code. My intention is to instantiate some objects for HTTP requests. I store their pointers in an array requestsBatch because I will call them from within a helper function. After storing them I'll do some time checks and then send the request to the server. After a successful request, the object will be deleted.
It seems the variable address is problematic but I can't see why.
const char* root_ca_sherz = "myCert";
int currentRequestsBatchIndex=0;
class HTTPREQUESTS {
public:
HTTPREQUESTS(String strAddress = "", String strParameters = "", bool bSendImmediately=false, const char* cert=root_ca_sherz) {
address = strAddress;
parameters = strParameters;
certificate = cert;
currentRequestsBatchIndex++;
Serial.println("New object instantiated");
Serial.println(address);
Serial.println(parameters);
}
~HTTPREQUESTS() {
currentRequestsBatchIndex--;
}
bool sendRequest() {
Serial.println("Called from within sendRequest()");
Serial.println(address); // <<<<<< THIS ROW CAUSES THE REBOOT
/*
http.begin(address+"/"+parameters, certificate); //, root_ca_sherz
int httpCode = http.GET();
Serial.print("HTTP Code: ");
Serial.println(httpCode);
Serial.print("Payload: ");
Serial.println(http.getString());
if (httpCode > 0) { //Check for the returning code
return true;
}
else {
Serial.println("Error on HTTP request");
return false;
}
http.end();
delay(1000);
return false;
*/
return true;
}
private:
const char* certificate="";
String parameters;
String device;
String address;
unsigned long timestamp=0;
int sendAttempts=0;
bool sendImmediately = false;
unsigned long lastSendAttemp=0;
};
HTTPREQUESTS *requestsBatch[5];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(3000);
Serial.println("Ready");
String address = "https://myAddress.com";
String parameters = "?secret=XXXXX&deviceName=deviceName&status=1&value=999&time=123456789&functionName=functionName";
HTTPREQUESTS *req01 = new HTTPREQUESTS(address, parameters);
// Store pointer to array to use it later
requestsBatch[currentRequestsBatchIndex] = req01;
Serial.println("Object stored in array");
Serial.print(F("Send request: "));
if(requestsBatch[0]->sendRequest()) {
//delete requestsBatch[0];
Serial.println("requestsBatch[0] deleted");
}
}
void loop() {
// put your main code here, to run repeatedly:
}
SOLUTION:
Replacing
currentRequestsBatchIndex++;
by
if(address != "") {
currentRequestsBatchIndex++;
}
because currentRequestsBatchIndex is also incrementing when creating the empty *requestsBatch[5] array.
As I dont like the String class (will cause you memory problems later on)I rewrote with char arrays and it works as expected (Included your "solution" but have you checked serial monitor output):
const char* root_ca_sherz = "myCert";
char address[128] = {'\0'};
int currentRequestsBatchIndex = 0;
class HTTPREQUESTS {
public:
HTTPREQUESTS(char strAddress[128] = {'\0'}, char strParameters [128] = {'\0'}, bool bSendImmediately = false, const char* cert = root_ca_sherz) {
strcpy (address, strAddress);
strcpy (parameters, strParameters);
certificate = cert;
if (address[0] != '\0') {
currentRequestsBatchIndex++;
}
currentRequestsBatchIndex++;
Serial.println("New object instantiated");
Serial.println(address);
Serial.println(parameters);
}
~HTTPREQUESTS() {
currentRequestsBatchIndex--;
}
bool sendRequest() {
char testAddress [128] = {'\0'};
Serial.println("Called from within sendRequest()");
strcpy (testAddress, address);
Serial.print("Will work: ");
Serial.println(testAddress); // <<<<<< THIS ROW CAUSES THE REBOOT
Serial.print("Will also work: ");
Serial.println(address); // but over written at next creation
/*
http.begin(address+"/"+parameters, certificate); //, root_ca_sherz
int httpCode = http.GET();
Serial.print("HTTP Code: ");
Serial.println(httpCode);
Serial.print("Payload: ");
Serial.println(http.getString());
if (httpCode > 0) { //Check for the returning code
return true;
}
else {
Serial.println("Error on HTTP request");
return false;
}
http.end();
delay(1000);
return false;
*/
return true;
}
private:
const char* certificate = "";
char parameters[128] = {'\0'};
char device[128] = {'\0'};
// char address[128] = {'\0'};
unsigned long timestamp = 0;
int sendAttempts = 0;
bool sendImmediately = false;
unsigned long lastSendAttemp = 0;
};
HTTPREQUESTS *requestsBatch[5];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(3000);
Serial.println("Ready");
const char address[] = "https://myAddress.com";
const char parameters[] = "?secret=XXXXX&deviceName=deviceName&status=1&value=999&time=123456789&functionName=functionName";
HTTPREQUESTS *req01 = new HTTPREQUESTS(address, parameters);
// Store pointer to array to use it later
requestsBatch[currentRequestsBatchIndex] = req01;
Serial.println("Object stored in array");
Serial.print(F("Send request: "));
if (requestsBatch[0]->sendRequest()) {
//delete requestsBatch[0];
Serial.println("requestsBatch[0] deleted");
}
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("Still running !");
delay(1000);
}

Data race while reading contents of archive with libarchive in thread. What I did wrong?

I`m trying to parallelize reading and processing archives, that are already in memory, but I get data race while calling libarchive function in a thread. Google sanitizer says that problem is in calling archive_read_open_memory function inside get_archive_contens. But I read that all functions in libarchive should be thread-safe. Can anyone tell me what I did wrong?
Here is my thread code.
void indexing_thread(std::mutex &m,
int &current_indexing_threads, concurrent_queue<std::pair<std::string, std::string>> &raw_files_q,
concurrent_queue<std::map<std::string, size_t>> &words_q) {
while (true) {
auto raw_file = raw_files_q.front();
std::string file_buffer = raw_file.first;
std::string ext = raw_file.second;
if (file_buffer.empty() && ext.empty()) {
break;
}
raw_files_q.pop();
std::string file_content;
if (ext == ".zip") {
auto archive_contents = get_archive_content(file_buffer);
for (int i = 0; i < archive_contents.size(); ++i) {
auto cur_ext = boost::filesystem::extension(archive_contents[i]);
if (cur_ext == ".txt") {
file_content = get_archive_file_contents(archive_contents[i], archive_contents, file_buffer);
file_content = convert_to_normalized_utf_string(file_content);
}
}
for (int i = 0; i < archive_contents.size(); ++i) {
auto cur_ext = boost::filesystem::extension(archive_contents[i]);
if (cur_ext == ".txt") {
file_content = get_archive_file_contents(archive_contents[i], archive_contents, file_buffer);
file_content = convert_to_normalized_utf_string(file_content);
}
}
}
auto words = word_count_map_nonparallel(file_content);
words_q.push_back(words);
}
m.lock();
current_indexing_threads--;
if (current_indexing_threads == 0) {
words_q.push_back(std::map<std::string, size_t>{});
}
m.unlock();
}
get_archive_content code:
std::string
get_archive_file_contents(const std::string &filename, std::vector<std::string> contents, std::string file_buffer) {
if (std::find(contents.begin(), contents.end(), filename) == contents.end()) {
throw FileDoesNotExistsException(filename);
}
struct archive_entry *entry;
struct archive *archive = archive_read_new();
archive_read_support_filter_all(archive);
archive_read_support_format_all(archive);
archive_read_support_format_raw(archive);
archive_read_support_format_empty(archive);
int reading_result = archive_read_open_memory(archive, file_buffer.data(), file_buffer.size());
if (reading_result != 0) {
throw std::runtime_error("Error reading archive");
}
void *buf;
int64_t length;
while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
if (archive_entry_filetype(entry) == AE_IFREG) {
length = archive_entry_size(entry);
buf = malloc(length);
if (!buf) {
archive_read_data_skip(archive);
continue;
}
archive_read_data(archive, buf, length);
break;
}
}
std::string result = static_cast<char *>(buf);
return result;
}
UPD: Google thread sanitizer report
I worked it out. The problem was in binary, that gets installed from ubuntu repositories. I solved this problem install libarchive from the sources.

Xcode C++ socket programming parse Issue Expected expression

I'm a newbie to socket programming and I'm trying to write a fork() function to enable the client to receive information sent by each four servers.
This is piece of the code I wrote, but it says parse Issue Expected expression.
I checked everything, used the "show invisible' but didn't work, the problem persist.
int pid = fork();
if(pid == 0)
{
close(tcp_socket);
char buffer[255]={0};
int bytes_num;
char serID[] = "0";
//std::string serID = "0";
// char serID[7] = "0";
while(true)
{
//recv(int sockfd, void *buf, size_t len, int flags);
bytes_num = recv(tcp_socket2,buffer,254,0);
if(bytes_num == 0)
{
break;
}
if(serID[] == "0")---------------->problem here
{
serID[]= buffer[0];
}
printf("serverID %s\n", serID);
if(serID[]=="serverA")---------------->problem here
{
//printf("NOW files!\n");
strcpy(str_file1[msg_num1],buffer);
msg_num1++;
}
if(serID[]=="serverB")---------------->problem here
{
strcpy(str_file2[msg_num2],buffer);
msg_num2++;
}
if(serID[]=="serverC")---------------->problem here
{
strcpy(str_file3[msg_num3],buffer);
msg_num3++;
}
if(serID[]=="serverD")---------------->problem here
{
strcpy(str_file4[msg_num4],buffer);
msg_num4++;
}
memset(buffer,0,sizeof(buffer));
}
if((serID[]=="serverA"))---------------->problem here
{
pf_file1 = fopen("rcvd_fileA.txt","w");
for(int i=0; i< msg_num1;i++)
{
//printf("now we read files!\n");
fprintf(pf_file1,"%s\n",str_file1[i]);
}
fclose(pf_file1);
}
if((serID[]=="serverB"))---------------->problem here
{
pf_file2 = fopen("rcvd_fileB.txt","w");
for(int i=0; i< msg_num2;i++)
{
fprintf(pf_file2,"%s\n",str_file2[i]);
}
fclose(pf_file2);
}
if((serID[]=="serverC"))---------------->problem here
{
pf_file3 = fopen("rcvd_fileC.txt","w");
for(int i=0; i< msg_num3;i++)
{
fprintf(pf_file3,"%s\n",str_file3[i]);
}
fclose(pf_file3);
}
if((serID[]=="serverD"))---------------->problem here
{
pf_file4 = fopen("rcvd_fileD.txt","w");
for(int i=0; i< msg_num4;i++)
{
fprintf(pf_file4,"%s\n",str_file4[i]);
}
fclose(pf_file4);
}
printf("The Client receives neighbor information from the Server %s with TCP port number %d and IP address %s \n",serID.c_str(),ntohs(sin.sin_port), ipstr);
close(tcp_socket2);
// printf("The Server %c has the following neighbor information: \n",serverID);
return 0;
}
////////////////////
I would really appreciate any one could help! Thanks in advance!

error: 'track_t' was not declared in this scope

I'm fiddling with an Arduino project where I've got these structs in my main file:
struct gpsCoord_t {
long latitude;
long longitude;
};
struct track_t {
char code[4];
gpsCoord_t bounds[4];
gpsCoord_t points[4];
};
Next to that I've got a function to dump variables of this type to the serial bus in that same file:
void dumpTrack(track_t track) {
Serial.print("\nTrack: ");
Serial.print(track.code);
Serial.print("\nTrack bounds: ");
Serial.print("\n- 1 lat: ");
Serial.print(track.bounds[0].latitude);
Serial.print("\n- 1 lon: ");
Serial.print(track.bounds[0].longitude);
}
The compiler produces 2 errors without line numbers from which I believe the first one is caused by the second one:
error: variable or field 'dumpTrack' declared void
error: 'track_t' was not declared in this scope
EDIT here's the complete file:
#include <Wire.h> //I2C library
#include <I2C_eeprom.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>
I2C_eeprom ee(0x50);
const int baseTrackAddress = 3;
const int trackSize = 68;
const int maxTracks = 480;
int powerOnLED = 2;
int gpsFixLED = 3;
int trackFoundLED = 4;
int errorLED = 6;
int gpsSensor = 7;
TinyGPS gps;
SoftwareSerial nss(gpsSensor, 255);
int calcTrackAddress(int trackId) {
return (trackId*trackSize) + baseTrackAddress;
}
struct gpsCoord_t {
long latitude;
long longitude;
};
struct track_t {
char code[4];
gpsCoord_t bounds[4];
gpsCoord_t points[4];
};
track_t tracks[maxTracks];
void setup()
{
Serial.begin(115200);
Serial.flush();
Serial.print("Demo I2C eeprom library ");
Serial.print(I2C_EEPROM_VERSION);
Serial.println("\n");
strcpy(tracks[0].code, "X11");
tracks[0].bounds[0].latitude = 0;
tracks[0].bounds[0].longitude = 0;
tracks[0].points[0].latitude = 0;
tracks[0].points[0].longitude = 0;
ee.writeBlock(3, (uint8_t*)&tracks[0], trackSize);
}
void loop()
{
Serial.println("\nTEST: 64 byte page boundary writeBlock");
dumpEEPROM(0, 255);
while(1);
}
void dumpTrack(track_t track) {
Serial.print("\nTrack: ");
Serial.print(track.code);
Serial.print("\nTrack bounds: ");
Serial.print("\n- 1 lat: ");
Serial.print(track.bounds[0].latitude);
Serial.print("\n- 1 lon: ");
Serial.print(track.bounds[0].longitude);
}
void readTrack(int trackId) {
track_t track;
ee.readBlock(60, (uint8_t*)&track, 10);
}
void readTracks() {
}
void dumpEEPROM(unsigned int addr, unsigned int length)
{
// block to 10
addr = addr / 10 * 10;
length = (length + 9)/10 * 10;
byte b = ee.readByte(addr);
for (int i = 0; i < length; i++)
{
if (addr % 10 == 0)
{
Serial.println();
Serial.print(addr);
Serial.print(":\t");
}
Serial.print(b);
b = ee.readByte(++addr);
Serial.print(" ");
}
Serial.println();
}
void ProcessCommand(char* command) {
//switch(*command==)
}
char* ReadSerialCommand() {
int i=0;
char commandbuffer[100];
if(Serial.available()){
delay(100);
while( Serial.available() && i< 99) {
commandbuffer[i++] = Serial.read();
}
commandbuffer[i++]='\0';
}
if(i>0)
return (char*)commandbuffer;
else
return 0L;
}
When I put the entire dumpTrack function in comment, the errors go away. I've checked a couple of times for a typo but failed to find any.
It seems you are compiling this code as C.
Instead of
struct track_t {
char code[4];
gpsCoord_t bounds[4];
gpsCoord_t points[4];
};
write
typedef struct {
char code[4];
gpsCoord_t bounds[4];
gpsCoord_t points[4];
} track_t;
I suspect somewhere in a header there is a variable called dumpTrack. Why don't you just rename the function to something else?
Also in general it is good to avoid using reserved words as function names; "loop" is not a good choice for a function name.
Edit: the latter is probably the reason for your problem.