c++ Unhandled exception: System.NullReferenceException - c++

i'm trying to get process name from Win32_Processor soo i create function ProcessNameInfo.
my code is :
void ProcessNameInfo(string nameoption, String^ hardwareClass, String^ propertyNname)
{
ManagementObjectSearcher^ searcher = gcnew ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + hardwareClass);
ManagementObjectCollection^ collection = searcher->Get();
for each (ManagementObject^ object in collection)
{
String ^ s = object[propertyNname]->ToString();
CString str3(s);
const TCHAR* x = (LPCTSTR)str3;
char szString[MAX_LENGTH];
size_t nNumCharConverted;
wcstombs_s(&nNumCharConverted, szString, MAX_LENGTH,
x, MAX_LENGTH);
std::string HardwareInfo = szString;
std::transform(HardwareInfo.begin(), HardwareInfo.end(), HardwareInfo.begin(), [](char ch) {
return ch == ' ' ? '_' : ch;
});
file << "\"" << nameoption << "\": \"" << HardwareInfo << "\"," << endl;
}
}
in the main i call this function like this :
ProcessNameInfo("Processor", "Win32_Processor", "Name");
for some devices it's working but in another devices i get error Unhandled exception:
System.NullReferenceException object reference not set to an instance of an object in ProcessNameInfo(basic_string<char\,std::char_traites<char>\,std::allocator<char> >* nameoption, String hardwareClass, String propertyNname) in main() _mainCRTStartup()

Related

Google Protobuf GetString & GetStringReference seems to get the wrong value

I am trying to get the string value from a protobuf message. My .proto schema looks like this:
syntax = "proto3";
package messages;
message Telemetry
{
optional string key1 = 1;
optional string key2 = 2;
}
The piece of code which is used to manipulate with it:
int main(int argc, char **argv)
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
messages::Telemetry telemetry;
// Initialize values
telemetry.set_key1("string_1");
telemetry.set_key2("string_2");
std::cout << "key1: " << telemetry.key1() << std::endl;
std::cout << "key2: " << telemetry.key2() << std::endl;
const google::protobuf::Descriptor *desc = telemetry.GetDescriptor();
int fieldCount = desc->field_count();
for(int i = 0; i < fieldCount ; i++)
{
const google::protobuf::FieldDescriptor *field = desc->FindFieldByNumber(i + 1);
fprintf(stderr, "Name of the %i th key: %s, type: %s \n", i, field->name().c_str(), field->type_name());
}
const google::protobuf::FieldDescriptor *field = desc->FindFieldByName("key1");
const google::protobuf::Reflection *refl = telemetry.GetReflection();
std::string str;
str = refl->GetStringReference(telemetry, field, &str);
std::cout << "Value: " << str << std::endl;
}
Somehow, the output looks like:
Name of the 0 th key: key1, type: string <- OK
Name of the 1 th key: key2, type: string <- OK
key1: string_1 <- OK
key2: string_2 <- OK
Value: string_2 <- This line is expected to be 'string_1'
Then if I tried desc->FindFieldByName("key2"), the program would be crashed with (Segmentation fault (core dumped)).
Thanks in advance for any suggestion.

Get all calls to specific function in source file and generate other files (using C, C++ preprocessor or scripts)

I have a program like below:
// test.c
#include <stdio.h>
#define LOG printf
int main(int argc, char *argv[])
{
LOG("Hello, my name %s, my age %d\n", "John", 30);
LOG("I have wife and %d kids\n", 2);
return 0;
}
I want to create a log file which contains all texts like:
// message.txt
LINE: "Hello, my name %s, my age %d\n"
LINE: "I have wife and %d kids\n"
Is it possible to do it using C's preprocessor, make, or even a script?
Edited:
Let's say I have a program that prints those messages in English already, I have source code for sure, now I want to support French then:
I need to get all messages that developers put into their program and create a message.txt which contains all texts, replace each message in original program with an identify number which maps each message in message.txt. I want to do it programmatically not manually.
What you are looking for is localization, read something about it here. If you're on a posix system you can use gettext() for that, see manpage. If you're using Windows you can take a look at GetText for Windows.
Nevertheless I wrote a little C++ program that generate the files you want, see code below.
You call it via myProg filename logFunction where filename is the source file you want to input and logFunction is for example LOG.
You will get a map file called filename_map and a new source file filename_new. The new source file will contain a new macro LOG and a function readLocaleStrings() which will read all the strings at program start from the filename_map file. The new macro LOG will use the right strings automatically then.
In your example you would call it by myProg test.c LOG and would get:
test_map.txt:
7: "Hello, my name %s, my age %d\n"
8: "I have wife and %d kids\n"
and a test_new.c:
// test.c
#include <stdio.h>
#define LOG(filename,line,...) printf(localeStrings.strings[localeStrings.lastIdx++], __VA_ARGS__)
/* Beginning: Generated code for localization */
#include <stdlib.h>
#include <string.h>
typedef struct {
size_t count;
size_t lastIdx;
char ** strings;
} stringArray_t;
stringArray_t localeStrings = { 0, 0, NULL };
int readLocaleStrings (const char * const filename)
{
FILE * file = NULL;
char * line = NULL;
char * str = NULL;
size_t len = 0;
ssize_t read;
file = fopen(filename, "r");
if (file == NULL)
{
return -1;
}
localeStrings.strings = malloc (sizeof (char *));
localeStrings.count = 0;
while (-1 != (read = getline(&line, &len, file)))
{
size_t curIdx = localeStrings.count++;
localeStrings.strings = realloc(localeStrings.strings, localeStrings.count * sizeof (char *));
str = strstr(line, "\"");
localeStrings.strings[curIdx] = malloc(sizeof (char) * (size_t)(1 + read));
strcpy (localeStrings.strings[curIdx], str);
}
fclose(file);
if (line)
{
free(line);
}
return 0;
}
void freeLocaleStrings()
{
size_t idx;
for (idx = 0; idx < localeStrings.count; ++idx)
{
free(localeStrings.strings[idx]);
}
free(localeStrings.strings);
}
/* End: Generated code for localization */
int main(int argc, char *argv[])
{
readLocaleStrings("test_map.txt");
LOG("test_map.txt", "7", "John", 30);
LOG("test_map.txt", "8", 2);
freeLocaleStrings();
return 0;
}
C++ program:
The C++ program has limitation, it will just find LOG(" if you want also to find LOG with spaces anywhere like: LOG (" you have to change that code. Moreover there are cases such as multiple lines messages, messages that had been commented out etc. You have to extend the code for your requirements then. Also there is no great argument parse handling or error checking. Further for the writing of the helper code it is needed to find the main function. But for your given input file it works perfectly and should just point you in the right direction. To extend it more easy and make it more flexible using a regex library would be wise.
Code:
#include <iostream>
#include <fstream>
/* Function definition is under main function */
const char * getNextHelperFunctionLine();
std::string getExtension (const std::string filename)
{
/* get dot of e.g. foo.c */
size_t posDot = filename.rfind('.');
/* extract extension */
std::string extension;
if (std::string::npos != posDot)
{
/* extension found */
extension = filename.substr(posDot);
}
return extension;
}
std::string getFilename (const std::string filename)
{
/* get dot of e.g. foo.c */
size_t posDot = filename.rfind('.');
/* extract filename */
std::string name = filename;
if (std::string::npos != posDot)
{
name = name.substr(0, posDot);
}
return name;
}
int main (int argc, char* argv[])
{
if (argc < 3)
{
std::cerr << "Usage: "
<< " " << argv[0] << " filename logFunction"
<< std::endl;
return 0;
}
std::string infileName (argv[1]);
/* extract filename and extension */
std::string filename = getFilename(infileName);
std::string extension = getExtension(infileName);;
/* names for generated files */
std::string mapfileName = filename + "_map.txt";
std::string mappedfileName = filename + "_new" + extension;
/* open streams for input and output */
std::ifstream infile(infileName.c_str());
std::ofstream fileMap(mapfileName.c_str());
std::ofstream fileMapped(mappedfileName.c_str());
/* string for log function e.g. "LOG(" */
std::string logFun = std::string(argv[2]);
std::string logFunOpen = logFun + "(\"";
std::string lineRead;
size_t lineNr = 1;
size_t mainParanthesis = 0;
bool mainReturnFound = false;
/* Loop through whole input file */
while (std::getline(infile, lineRead))
{
/* position of log function opening e.g. "LOG(" */
size_t posLogOpen = lineRead.find(logFunOpen);
/* opening found? */
bool foundOpen = std::string::npos != posLogOpen;
if (foundOpen)
{
bool foundClose = false;
/* position of the string beginning */
size_t posLogStringBeg = posLogOpen + logFunOpen.length();
size_t posLogClose = posLogStringBeg;
/* find closing of the log function e.g. "LOG(...)" */
while (!foundClose)
{
/* search for '"' and skip these if they are in the string */
posLogClose = lineRead.find("\"", posLogClose + 1);
if (std::string::npos != posLogClose)
{
foundClose = (0 != lineRead.compare(posLogClose - 1, 1, "\\"));
}
}
/* closing found write map file and new source file */
if (foundClose)
{
size_t len = posLogClose - posLogStringBeg;
fileMap << lineNr << ": \""
<< lineRead.substr(posLogStringBeg, len) << "\""
<< std::endl;
fileMapped << lineRead.substr(0, posLogStringBeg - 1)
<< '"' << mapfileName << "\", "
<< '"' << lineNr
<< lineRead.substr(posLogClose)
<< std::endl;
}
}
/* not a log function write normal code */
else
{
if ( std::string::npos != lineRead.find("#define")
&& std::string::npos != lineRead.find(logFun))
{
/* log functions needs to be changed */
fileMapped << "#define "
<< logFun << "(filename,line,...) "
<< "printf(localeStrings.strings[localeStrings.lastIdx++], __VA_ARGS__)" << std::endl;
}
else if ( 0 == mainParanthesis
&& std::string::npos != lineRead.find(" main")
&& std::string::npos != lineRead.find("(")
&& std::string::npos != lineRead.find(")"))
{
/* found main function write all helper functions in front of it */
const char * helperLine;
while ((helperLine = getNextHelperFunctionLine()))
{
fileMapped << helperLine << std::endl;
}
/* write main function part */
fileMapped << lineRead << std::endl;
/* is there an opening parenthesis? */
if (std::string::npos != lineRead.find("{"))
{
++mainParanthesis;
fileMapped << " readLocaleStrings(\"" << mapfileName << "\");" << std::endl;
}
}
else
{
/* in main function write first part */
if (std::string::npos != lineRead.find("{"))
{
/* write opening */
fileMapped << lineRead << std::endl;
if (0 == mainParanthesis)
{
fileMapped << " readLocaleStrings(\"" << mapfileName << "\");" << std::endl;
}
++mainParanthesis;
}
/* return statement? */
else if ( 1 == mainParanthesis
&& std::string::npos != lineRead.find("return"))
{
mainReturnFound = true;
fileMapped << " freeLocaleStrings();" << std::endl;
/* write return */
fileMapped << lineRead << std::endl;
}
else if ( 1 == mainParanthesis
&& std::string::npos != lineRead.find("}"))
{
--mainParanthesis;
if (!mainReturnFound)
{
fileMapped << " freeLocaleStrings();" << std::endl;
}
/* write closing */
fileMapped << lineRead << std::endl;
}
else
{
/* write other code */
fileMapped << lineRead << std::endl;
}
}
}
++lineNr;
}
return 0;
}
const char * getNextHelperFunctionLine()
{
static size_t idx = 0;
static const char * helperFunLines[] =
{
"",
"/* Beginning: Generated code for localization */",
"#include <stdlib.h>",
"#include <string.h>",
"",
"typedef struct {",
" size_t count;",
" size_t lastIdx;",
" char ** strings;",
"} stringArray_t;",
"",
"stringArray_t localeStrings = { 0, 0, NULL };",
"",
"int readLocaleStrings (const char * const filename)",
"{",
" FILE * file = NULL;",
" char * line = NULL;",
" char * str = NULL;",
" size_t len = 0;",
" ssize_t read;",
"",
" file = fopen(filename, \"r\");",
" if (file == NULL)",
" {",
" return -1;",
" }",
"",
" localeStrings.strings = malloc (sizeof (char *));",
" localeStrings.count = 0;",
"",
" while (-1 != (read = getline(&line, &len, file)))",
" {",
" size_t curIdx = localeStrings.count++;",
" localeStrings.strings = realloc(localeStrings.strings, localeStrings.count * sizeof (char *));",
"",
" str = strstr(line, \"\\\"\");",
" localeStrings.strings[curIdx] = malloc(sizeof (char) * (size_t)(1 + read));",
" strcpy (localeStrings.strings[curIdx], str);",
" }",
"",
" fclose(file);",
" if (line)",
" {",
" free(line);",
" }",
"",
" return 0;",
"}",
"",
"void freeLocaleStrings()",
"{",
" size_t idx;",
" for (idx = 0; idx < localeStrings.count; ++idx)",
" {",
" free(localeStrings.strings[idx]);",
" }",
" free(localeStrings.strings);",
"}",
"/* End: Generated code for localization */",
""
};
if (idx < (sizeof (helperFunLines) / sizeof (helperFunLines[0])))
{
return helperFunLines[idx++];
}
else
{
return nullptr; /* use NULL if compiler doesn't support nullptr */
}
}

ofstream doesn't work when the variable is an attribute

This implementation of ofstream works :
bool LinuxSysCall::addNewUser(std::string const &login, std::string const &password) {
std::ofstream out;
out.open(DATABASEPATH, std::ios::app);
if (out.is_open())
{
std::string str = login + ":" + password + "\n";
std::cout << "writing " << str << std::endl;
out << str;
return true;
}
return false;
}
//The new line is written in the file
But when I put my std::ofstream out as an attribute of LinuxSysCall, it doesn't work anymore (without trowing any exceptions):
bool LinuxSysCall::addNewUser(std::string const &login, std::string const &password) {
this->out.open(DATABASEPATH, std::ios::app);
if (this->out.is_open())
{
std::string str = login + ":" + password + "\n";
std::cout << "writing " << str << std::endl;
this->out << str;
return true;
}
return false;
}
//The new line is not written in the file
Why ?
The destructor of std::ofstream calls close. This will flush the text to the file.
If you want to use a member variable (not "attribute") you would need:
bool LinuxSysCall::addNewUser(std::string const &login,
std::string const &password) {
this->out.open(DATABASEPATH, std::ios::app);
if (this->out.is_open())
{
std::string str = login + ":" + password + "\n";
std::cout << "writing " << str << std::endl;
this->out << str;
this->out.close();
return true;
}
return false;
}
As it stands, using a member variable is much worse than using the local - however, I suspect you actually want to pass the open file around amongst many member functions. If so, you can flush the output with:
this->out << std::flush;
without closing it.

Data gets lost after returning pointer to vector of pointers to objects

first post ever here... I'm trying to get this code to work, it compiles but throws out a seg. fault when I try to access the data using the pointer after the function returns. I guess the data is deleted after the function ends so the pointer is lost. I have searched a lot and thought that the only way to fix it is if some else can take a look at my code and point me in the right direction. Thanx a lot in advance.
/*
* Compile with:
* g++ -std=c++11 -o gsoap_pf_download_config main.cpp soapC.cpp \
* soapBasicHttpBinding_USCOREIPagaFacilCobroServiceProxy.cpp -lgsoap++
*/
#include "soapBasicHttpBinding_USCOREIPagaFacilCobroServiceProxy.h"
#include "BasicHttpBinding_USCOREIPagaFacilCobroService.nsmap"
#include <string>
std::string BVserialNum = "ACF90004";
std::string BVid = "215";
std::string latitud = "0";
std::string longitud = "0";
class SoapClient {
ns2__ParametrosEnvio *parameters;
ns2__ArrayOfParametrosEnvio *parametersArray;
public:
int downloadConfig();
private:
std::string getToken(std::string date, std::string time);
std::string getProcessKey(std::string token);
int createClient(_tempuri__AperturaTerminalConsumo &client);
};
int SoapClient::createClient(_tempuri__AperturaTerminalConsumo &client) {
timeval curTime;
gettimeofday(&curTime, NULL);
std::string date = getDate(curTime);
std::string time = getTime(curTime);
std::string timeMicro = getTimeWithMicroSecs(curTime);
std::string token = getToken(date, time);
std::string processKey = getProcessKey(token);
ns2__ParametrosEnvio *arrayParam1 = new ns2__ParametrosEnvio();
ns2__ParametrosEnvio *arrayParam2 = new ns2__ParametrosEnvio();
ns2__ParametrosEnvio *arrayParam3 = new ns2__ParametrosEnvio();
ns2__ParametrosEnvio *arrayParam4 = new ns2__ParametrosEnvio();
ns2__ParametrosEnvio *arrayParam5 = new ns2__ParametrosEnvio();
ns2__ParametrosEnvio *arrayParam6 = new ns2__ParametrosEnvio();
ns2__ParametrosEnvio *arrayParam7 = new ns2__ParametrosEnvio();
std::string tokenStr = "TerminalToken";
std::string processKeyStr = "LlaveProceso";
std::string serialNumStr = "TerminalSerie";
std::string dateStr = "TerminalFecha";
std::string timeStr = "TerminalHora";
std::string latStr = "Latitud";
std::string lonStr = "Longitud";
arrayParam1->Key = &tokenStr;
arrayParam1->Data = &token;
arrayParam2->Key = &processKeyStr;
arrayParam2->Data = &processKey;
arrayParam3->Key = &serialNumStr;
arrayParam3->Data = &BVserialNum;
arrayParam4->Key = &dateStr;
arrayParam4->Data = &date;
arrayParam5->Key = &timeStr;
arrayParam5->Data = &time;
arrayParam6->Key = &latStr;
arrayParam6->Data = &latitud;
arrayParam7->Key = &lonStr;
arrayParam7->Data = &longitud;
std::vector<ns2__ParametrosEnvio* > parametersVector;
parametersVector.push_back(arrayParam1);
parametersVector.push_back(arrayParam2);
parametersVector.push_back(arrayParam3);
parametersVector.push_back(arrayParam4);
parametersVector.push_back(arrayParam5);
parametersVector.push_back(arrayParam6);
parametersVector.push_back(arrayParam7);
ns2__ArrayOfParametrosEnvio parametersArray;
parametersArray.ParametrosEnvio = parametersVector;
ns2__ParametrosEnvio parameters;
parameters.ListaDatos = &parametersArray;
client.Parametros = &parameters;
int i = 0;
for (std::vector<ns2__ParametrosEnvio* >::iterator it = \
parametersVector.begin(); it != parametersVector.end(); ++it) {
std::cout << *it << ":" \
<< *client.Parametros->ListaDatos->ParametrosEnvio.at(i)->Key << ":" \
<< *client.Parametros->ListaDatos->ParametrosEnvio.at(i)->Data \
<< std::endl;
++i;
}
return SOAP_OK;
}
int SoapClient::downloadConfig() {
BasicHttpBinding_USCOREIPagaFacilCobroServiceProxy service;
_tempuri__AperturaTerminalConsumo client;
_tempuri__AperturaTerminalConsumoResponse response;
createClient(client);
std::cout << *client.Parametros->ListaDatos->ParametrosEnvio.at(0)->Key << std::endl;
std::cout << *client.Parametros->ListaDatos->ParametrosEnvio.at(1)->Key << std::endl;
std::cout << *client.Parametros->ListaDatos->ParametrosEnvio.at(2)->Key << std::endl;
std::cout << *client.Parametros->ListaDatos->ParametrosEnvio.at(3)->Key << std::endl;
std::cout << *client.Parametros->ListaDatos->ParametrosEnvio.at(4)->Key << std::endl;
std::cout << *client.Parametros->ListaDatos->ParametrosEnvio.at(5)->Key << std::endl;
std::cout << *client.Parametros->ListaDatos->ParametrosEnvio.at(6)->Key << std::endl;
int ret = service.AperturaTerminalConsumo(&client, response);
if (ret == SOAP_OK) {
std::cout << "id:" << *response.AperturaTerminalConsumoResult-> \
TerminalConsumo->Id << std::endl;
std::cout << "locality:" << *response.AperturaTerminalConsumoResult-> \
TerminalConsumo->LocalidadDispositivoId << std::endl;
std::cout << "route:" << *response.AperturaTerminalConsumoResult-> \
Ruta->Id << std::endl;
std::cout << "fare:" << *response.AperturaTerminalConsumoResult-> \
Ruta->Tarifa << std::endl;
}
else
service.soap_stream_fault(std::cerr);
service.destroy(); // delete data and release memory
}
int main()
{
SoapClient client;
client.downloadConfig();
}
``
Lets look at these lines:
ns2__ArrayOfParametrosEnvio parametersArray;
...
ns2__ParametrosEnvio parameters;
parameters.ListaDatos = &parametersArray;
client.Parametros = &parameters;
Here you declare the local variables parametersArray and parameters, then you save pointers to these variables.
When the function returns these variables go out of scope and the objects are destructed. The pointers you have saved no longer points to valid objects. Trying to use them will lead to undefined behavior.
You have two solutions: Either you don't use pointers, but copy the objects instead (my recommendation). Or you need to allocate these object dynamically with new (and remember to free them with delete).

Simplest way to validate a GPS string in C++?

I have some MET data I want to validate which would look something like these:
char validBuffer[] = {"N51374114W1160437"};
char invalidBuffer[] = {"bad data\n"};
char emptyBuffer[] = {""};
I've tried a simple sscanf, but that failed:
int _tmain(int argc, _TCHAR* argv[])
{
char validBuffer[] = {"N51374114W1160437"};
char invalidBuffer[] = {"bad data\n"};
char emptyBuffer[] = {""};
char ns = ' ';
char ew = ' ';
int northing = -999;
int easting = -999;
int paramsConverted = sscanf_s(validBuffer, "%c%d%c%d", &ns, &northing, &ew, &easting);
printf("Converted \"%s\"; Found %d params [%c,%d,%c,%d]\n", validBuffer, paramsConverted, ns, northing, ew, easting);
paramsConverted = sscanf_s(invalidBuffer, "%c%d%c%d", &ns, &northing, &ew, &easting);
printf("Converted \"%s\"; Found %d params [%c,%d,%c,%d]\n", invalidBuffer, paramsConverted, ns, northing, ew, easting);
paramsConverted = sscanf_s(validBuffer, "%c%d%c%d", &ns, &northing, &ew, &easting);
printf("Converted \"%s\"; Found %d params [%c,%d,%c,%d]\n", emptyBuffer, paramsConverted, ns, northing, ew, easting);
getchar();
return 0;
}
gives me:
Converted "N51374114W1160437"; Found 2 params [N,-999,",-1024]
Converted "bad data
"; Found 1 params [b,-999,",-1024]
Converted ""; Found 2 params [N,-999,",-1024]
I'd rather not use any external libraries if at all possible, so is there a nice simple way of doing this without parsing it one character at a time?
How about using Regular expressions from TR1?
char validBuffer[] = {"N51374114W1160437"};
char invalidBuffer[] = {"bad data\n"};
char emptyBuffer[] = {""};
if(strlen(validBuffer)!=18)
{
//Error not valid buffer
}
char ns = validBuffer[0];
char ew = validBuffer[9];
int N = atoi(&validBuffer[1]);
int W = atoi(&validBuffer[10]);
if(N==0 || W==0)
//Error not valid buffer
Not simple not the best but better than nothing
You could use std::stringstream and the stream operators...
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
bool parse(string & s) {
stringstream ss(s);
char n = 0, w = 0;
int x = 0, y = 0;
ss >> n;
if (! ss.good ()) return false;
ss >> x;
if (! ss.good ()) return false;
ss >> w;
if (! ss.good ()) return false;
ss >> y;
if ( ss.bad ()) return false;
cout << "Parsed {" << n << ", " << x << ", "
<< w << ", " << y << "}" << endl;
return true;
}
int main ()
{
string validBuffer = "N51374114W1160437";
string invalidBuffer = "bad data\n";
string emptyBuffer = "";
if (! parse (validBuffer))
cout << "Unable to parse: '" << validBuffer << "'" << endl;
if (! parse (invalidBuffer))
cout << "Unable to parse: '" << invalidBuffer << "'" << endl;
if (! parse (emptyBuffer))
cout << "Unable to parse: '" << emptyBuffer << "'" << endl;
return 0;
}
My output using the above:
Parsed {N, 51374114, W, 1160437}
Unable to parse: 'bad data
'
Unable to parse: ''
Consider a bit specific format parameter for sscanf():
int paramsConverted = sscanf(validBuffer, "%c%8d%c%7d", &ns, &northing, &ew, &easting);