I want to use protocol buffer to send and receive the following type using gRPC
std:array<std::complex<int>, 2> bar_array;
Sources used to get idea: 1, 2
What I have done so far
My approach (Intentionally I am omitting here the unnecessary code)
proto file
syntax = "proto3";
package expcmake;
message child_data {
repeated int32 child_data_list = 1;
}
message Address {
child_data child_data_var = 8;
repeated child_data parent_data_list = 9;
}
server.cpp
Here, at first I have made a dummy std:array<std::complex<int>, 2> data. Then, I have filled the child_data_list with the std::complex<int> data. After each filling of real and imaginary part I have pushed them in the parent_data_list. Also, at this moment I have cleared the child_data_list.
Client message name is NameQuery, while Server message name is Address
In Server side both message are passed as pointer
class AddressBookService final : public expcmake::AddressBook::Service {
public:
virtual ::grpc::Status GetAddress(::grpc::ServerContext* context, const ::expcmake::NameQuery* request, ::expcmake::Address* response)
{
// omitting unnecessary lines
// populate bar_array with std::complex<int> data
std::complex<int> z4 = 1. + 2i, z5 = 1. - 2i; // conjugates
bar_array = {z4, z5};
std::cout << "bar array printing whose size: " << bar_array.size() << std::endl;
for(int i = 0; i < bar_array.size(); i++) {
std::cout << bar_array[i] << " ";
}
std::cout << std::endl;
// Use parent_data_list protocol buffer message type to fill with the content of bar_array
for (int i = 0; i < bar_array.size(); i++){
// Use child_data protocol buffer message type to fill with the content of complex int data
response->mutable_child_data_var()->add_child_data_list(real(bar_array[i]));
response->mutable_child_data_var()->add_child_data_list(imag(bar_array[i]));
// Use parent_data_list protocol buffer message type to fill with the content of child_data -> child_data_list data
response->add_parent_data_list() -> child_data_list();
// clear the child_data message. Reason to keep child_data_list new in every iteration otherwise add_child_data_list will append new data (eg: 1,2,1,-2) which is wrong. Expected is (1,2) then (1,-2)
response->mutable_child_data_var()->clear_child_data_list();
}
// This is zero which I have got. Without clearing it is 4 which is also correct I believe as per the concept of protocol buffer message type
std::cout << "response->mutable_child_data_var()->child_data_list_size(): " << response->mutable_child_data_var()->child_data_list_size() << std::endl;
// This is 2 which meets my requirement
std::cout << "response->parent_data_list_size(): " << response->parent_data_list_size() << std::endl;
// omitting unnecessary lines
}
};
client.cpp
int main(int argc, char* argv[])
{
// Setup request
expcmake::NameQuery query;
expcmake::Address result;
// printing the content of child_data -> child_data_list data array/container. There I have seen 1,2,1,-2 if I don't do the clear operation on child_data_list in server side. So, I guess it is correctly got the data
for(int i = 0; i < result.mutable_child_data_var()->child_data_list_size(); i++)
std::cout << "Child Data at index [" << i << "]: " << result.mutable_child_data_var()->child_data_list(i) << std::endl;
// This one making problem
// printing the content of parent_data_list type/container
// for(int i = 0; i < result.parent_data_list_size(); i++){
// std::cout << "Parent Data at index [" << i << "]: " << result.mutable_parent_data_list(i) << std::endl; // This give me the memory address
// Tried others to fetch the data but failed. Eg: result.parent_data_list(i) // failed
//
// }
}
Snippet from the generated pb file
// repeated int32 child_data_list = 1;
int child_data_list_size() const;
private:
int _internal_child_data_list_size() const;
public:
void clear_child_data_list();
private:
::PROTOBUF_NAMESPACE_ID::int32 _internal_child_data_list(int index) const;
const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >&
_internal_child_data_list() const;
void _internal_add_child_data_list(::PROTOBUF_NAMESPACE_ID::int32 value);
::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >*
_internal_mutable_child_data_list();
public:
::PROTOBUF_NAMESPACE_ID::int32 child_data_list(int index) const;
void set_child_data_list(int index, ::PROTOBUF_NAMESPACE_ID::int32 value);
void add_child_data_list(::PROTOBUF_NAMESPACE_ID::int32 value);
const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >&
child_data_list() const;
::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >*
mutable_child_data_list();
// .expcmake.child_data child_data_var = 8;
bool has_child_data_var() const;
private:
bool _internal_has_child_data_var() const;
public:
void clear_child_data_var();
const ::expcmake::child_data& child_data_var() const;
PROTOBUF_MUST_USE_RESULT ::expcmake::child_data* release_child_data_var();
::expcmake::child_data* mutable_child_data_var();
void set_allocated_child_data_var(::expcmake::child_data* child_data_var);
private:
const ::expcmake::child_data& _internal_child_data_var() const;
::expcmake::child_data* _internal_mutable_child_data_var();
public:
void unsafe_arena_set_allocated_child_data_var(
::expcmake::child_data* child_data_var);
::expcmake::child_data* unsafe_arena_release_child_data_var();
// repeated .expcmake.child_data parent_data_list = 9;
int parent_data_list_size() const;
private:
int _internal_parent_data_list_size() const;
public:
void clear_parent_data_list();
::expcmake::child_data* mutable_parent_data_list(int index);
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::expcmake::child_data >*
mutable_parent_data_list();
private:
const ::expcmake::child_data& _internal_parent_data_list(int index) const;
::expcmake::child_data* _internal_add_parent_data_list();
public:
const ::expcmake::child_data& parent_data_list(int index) const;
::expcmake::child_data* add_parent_data_list();
const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::expcmake::child_data >&
parent_data_list() const;
I guess
Is the filling of the message field is incorrectly done !! Though the size is not saying that
I am not catching the protobuf syntax(which is generated in the pb file) in right way to fetch the data
Need suggestions(helpful if can provide the syntax too).
The mutable_* prefixed APIs are for mutating (modifying/adding) elements and they return a pointer. The mutable_* and set_* APIs should only be used while filling the data. Once data is filled, you should not be using mutable_* APIs to check sizes. After receiving the response from the server, the client will most probably be consuming it, not mutating. You need to update the client-side accordingly.
Also, you can use a range-based for loop to iterate over child_data_list of child_data_var like this:
const auto child_data_list = result.child_data_var().child_data_list();
for (const auto element : child_data_list)
{
// process element
}
Apart from that, you're using std::array (a fixed-size array) i.e. std:array<std::complex<int>, 2>, alternatively here's another way to model this without repeated which does not represent a fixed-size array.
complex.proto
syntax = "proto3";
package pb;
message Complex {
int32 real = 1;
int32 imag = 2;
}
message Compound {
Complex c1 = 1;
Complex c2 = 2;
}
The message Complex emulates an std::complex type and Compound an std::array with only 2 elements c1 and c2.
With this, you can easily convert the protobuf message to std::complex and vice versa. Once converted to std::complex, you can perform its supported operations as needed.
Compile complex.proto:
protoc --cpp_out=. ./complex.proto
For the C++ API, look for the accessors in the generated complex.pb.h file under public. The official doc Protocol Buffer Basics: C++ also lists the C++ API examples under The Protocol Buffer API section.
Here's a complete C++ example with the above complex.proto:
main.cpp
#include <iostream>
#include <complex>
#include <array>
#include <cstdlib>
#include "complex.pb.h"
namespace my {
using complex = std::complex<int>;
using compound = std::array<std::complex<int>, 2>;
}
int main()
{
const auto my_c1 = my::complex{ 1, 2 };
const auto my_c2 = my::complex{ 2, 4 };
const auto my_compound_1 = my::compound{ my_c1, my_c2 };
std::cout << "my_compound_1 [size: " << my_compound_1.size() << "]\n";
std::cout << "my_c1: " << my_c1 << '\n';
std::cout << "my_c2: " << my_c2 << '\n';
pb::Compound pb_compound;
pb_compound.mutable_c1()->set_real(my_compound_1[0].real());
pb_compound.mutable_c1()->set_imag(my_compound_1[0].imag());
pb_compound.mutable_c2()->set_real(my_compound_1[1].real());
pb_compound.mutable_c2()->set_imag(my_compound_1[1].imag());
std::cout << "\npb_compound:\n";
pb_compound.PrintDebugString();
const auto serialized_compound = pb_compound.SerializeAsString();
// send
// receive
pb::Compound deserialized_compound;
if (!deserialized_compound.ParseFromString(serialized_compound))
{
std::cerr << "[ERROR] Parsing failed!\n";
return EXIT_FAILURE;
}
std::cout << "\n\npb_compound (deserialized):\n";
deserialized_compound.PrintDebugString();
const auto pb_c1 = deserialized_compound.c1();
const auto pb_c2 = deserialized_compound.c2();
const auto my_c3 = my::complex{ pb_c1.real(), pb_c1.imag() };
const auto my_c4 = my::complex{ pb_c2.real(), pb_c2.imag() };
const auto my_compound_2 = my::compound{ my_c3, my_c4 };
std::cout << "my_compound_2 [size: " << my_compound_2.size() << "]\n";
std::cout << "my_c3: " << my_c3 << '\n';
std::cout << "my_c4: " << my_c4 << '\n';
const auto sum = my_c3 + my_c4;
std::cout << "sum: " << sum << '\n';
return EXIT_SUCCESS;
}
Compile with g++:
g++ main.cpp complex.pb.cc -o pb_complex `pkg-config --cflags --libs protobuf`
Run:
$ ./pb_complex
my_compound_1 [size: 2]
my_c1: (1,2)
my_c2: (2,4)
pb_compound:
c1 {
real: 1
imag: 2
}
c2 {
real: 2
imag: 4
}
pb_compound (deserialized):
c1 {
real: 1
imag: 2
}
c2 {
real: 2
imag: 4
}
my_compound_2 [size: 2]
my_c3: (1,2)
my_c4: (2,4)
sum: (3,6)
The way I was accessing the filed parent_data_list was wrong. I am posting the approach which has solved the issue.
A little change in proto file
syntax = "proto3";
package expcmake;
message child_data {
repeated int32 child_data_list = 1 [packed=true];
}
message Address {
repeated child_data parent_data_list = 1;
}
Reason to use packed see this
server.cpp
class AddressBookService final : public expcmake::AddressBook::Service {
public:
virtual ::grpc::Status GetAddress(::grpc::ServerContext* context, const ::expcmake::NameQuery* request, ::expcmake::Address* response){
// omitting unnecessary lines
// populate bar_array with std::complex<int> data
std::complex<int> z4 = 1. + 2i, z5 = 1. - 2i; // conjugates
bar_array = {z4, z5};
// Now goal is to pass this bar_array as a protobuf message
// Use parent_data_list protocol buffer message type to fill with the content of bar_array
for (int i = 0; i < bar_array.size(); i++){
// make a 2D array. Eg: std::array<std::complex<int>>. In each iteration, new sub_content will be added (here sub_content means child_data_list)
response->add_parent_data_list() -> child_data_list();
// Followings are filling the child_data_list with the required data(Real and Imag part of the complex data which is already generated)
response->mutable_parent_data_list(i)->add_child_data_list(real(bar_array[i]));
response->mutable_parent_data_list(i)->add_child_data_list(imag(bar_array[i]));
}
}
return grpc::Status::OK;
};
After the completion of the iteration, A 2D type of message will be generated which is parent_data_list = [[child_data_list], [child_data_list]]. Don't consider it as a real scenario. Just for presentation I am using it.
client.cpp
std::cout <<"Using Mutable" << std::endl;
for(int i = 0; i < result.parent_data_list_size(); i++){
for(int j = 0 ; j<result.mutable_parent_data_list(i)->child_data_list_size(); j++){
std::cout << "Value [" << i << "][" << j << "]: " << result.mutable_parent_data_list(i)->child_data_list(j) << std::endl;
}
}
// Following is same as before. Added as I was in turmoil to understand the properties generated by protobuf. Hope could be helpful for beginners like me
std::cout <<"Without Mutable property" << std::endl;
for(int i = 0; i < result.parent_data_list_size(); i++){
for(int j = 0 ; j < result.parent_data_list(i).child_data_list_size(); j++){
std::cout << "Value [" << i << "][" << j << "]: " << result.parent_data_list(i).child_data_list(j) << std::endl;
}
}
In client side I am accessing the child_data_list with index which is not properly mimic the C++ style. Would be great if I can in one line print the value of parent_data_list[n] data. As far I have studied the generated pb.h file my understanding is that it is not possible as no return function I have not found without index for the repeated field. Or may be I am missing something important again.
Related
#include iostream
#include cmath
#include fstream
#include cstdlib
#include string
using namespace std;
class Device {//Input and store Device Description and Serial Numbers
protected:
static string serial_number;
static string device_description;
public:
Device() {
serial_number = ("6DCMQ32");
device_description = ("TheDell");
}
Device(string s, string d) {
serial_number = s;
device_description = d;
}
};
string Device::device_description;
string Device::serial_number;
class Test {//Input and store Test Description, recent day, and month;
Calculate the next day
protected:
static string Test_Description;
static int recent_month, recent_day, recent_year, new_month;
static int nmonth, next_month, next_day, next_year, max_day;
public:
Test() {
Test_Description = ("Virtual");
}
static void getMonth() {//Calculates the next/new month
next_month = recent_month + nmonth;
new_month = next_month % 12;
if (next_month >= 12) {
cout << "The next Date: " << new_month << " / ";
}
else {
cout << "The next Date: " << next_month << " / ";
}
}
static void getDay() { //Calculates day of next month
if (new_month == 4 || new_month == 6 || new_month == 9 || new_month == 11) {
max_day = 30;
}
else if (new_month == 2) {
max_day = 29;
}
else {
max_day = 31;
}
if (recent_day > max_day) {
cout << max_day << " / ";
}
else {
cout << recent_day << " / ";
}
}
static void getYear() {// Calculate the year of next month
next_year = recent_year + next_month;
if (next_year >= 12) {
cout << recent_year + (next_month / 12) << endl;
}
else {
cout << next_year << endl;
}
}
static void getDate() {// Collects the output of each element of next date
Test::getMonth(), Test::getDay(), Test::getYear();
}
};
string Test::Test_Description;
int Test::recent_month;
int Test::recent_day;
int Test::recent_year;
int Test::new_month;
int Test::nmonth;
int Test::next_month;
int Test::next_day;
int Test::next_year;
int Test::max_day;
class Lab : public Device, public Test {
protected:
static int n;
public:
friend istream & operator>>(istream & in, Lab & lab) {// Inputs
cout << "Enter Device Desciption and Serial Number: ";
getline(in, device_description);
getline(in, serial_number);
cout << "Enter Test Desciption: ";
getline(in, Test_Description);
cout << "Enter the Number of months: ";
in >> nmonth;
cout << "Enter the Most Recent Date(mm/dd/yyyy): ";
in >> recent_month >> recent_day >> recent_year;
return in;
}
friend ostream & operator<<(ostream & out, Lab & lab) {//Outputs
everything in Device Class
out << Lab::device_description << endl;
out << Lab::serial_number << endl;
out << Lab::Test_Description << endl;
getDate();
return out;
}
static void getN() {
cout << "Enter the number of devices: ";
cin >> n;
}
static void getWrite() {
Lab *obj = new Lab[n];
if (obj == 0) {
cout << "Memory Error";
exit(1);
}
for (int i = 0; i<n; i++) {
cin >> obj[i];
cout << endl;
}
ofstream myfile("Device.txt");
myfile.write((char *)obj, n * sizeof(Lab));
delete[] obj;
}
static void getRead() {
ifstream file2("Device.txt");
Lab *obj2 = new Lab[n];
if (obj2 == 0) {
cout << "Memory Error";
exit(1);
}
file2.read((char *)obj2, n * sizeof(Lab));
for (int i = 0; i < n; i++) {
cout << obj2[i];
cout << endl;
}
delete[] obj2;
}
/*void getSearch(){
}*/
};
int Lab::n;
void main() {
Lab L;
L.getN();
L.getWrite();
L.getRead();
system("pause");
}
The Output I get is TheDell 6DCMQ32, Virtual when I entered my inputs. The date is correct the only problem is the Device Description, Serial Number, and Test Device.
Problem with Operator << in File i/o reading where it outputs the values in the Constructor
Purpose: is to enter the number of months for the next test date of device with input of serial number,
Device Description, Test Description, recent date, and the number of months of two tests. At the end the
program must be searched by having the user to input the serial number and the next date, if these two are
valid everything in the device is listed out.
Short of writing your application, I will do my best to give you some direction.
#include <iostream> // Note the '<' and '>' this is to specify is a language provided include
// More includes with the same issue...
using namespace std; // this is general considered bad=practice see https://stackoverflow.com/a/1452738/8480874 for details
//Input and store Device Description and Serial Numbers
class Device
{ // Notice the white space makes it easier to read...
protected:
//static string serial_number; // declaring this static means _EVERY_ device will have the same serial number
//static string device_description; // same as above
string serialNumber;
string deviceDesc;
public:
Device() : serialNumber("6DCMQ32"), deviceDesc("TheDell")
{
//serial_number = ("6DCMQ32"); // Not the best place for initialization
//device_description = ("TheDell"); // Not the best place for initialization
}
//Device(string s, string d) // you never actually use this
//{
// serial_number = s;
// device_description = d;
//}
};
//string Device::device_description; // This is a sign that you variable will be shared between everyone - not required if you remove the static
//string Device::serial_number; // This is a sign that you variable will be shared between everyone - not required if you remove the static
// This suffers from the same probles as the `class device` above
class Test
{
// Lots of stuff was here just trying to short the answer....
// Mostly has the same culprits mentions for the device
// This is one of the fucntions which gets called when you are trying to "save" the info to a file
static void getMonth(/* ostream & out */) // you need this as a paramater
{
next_month = recent_month + nmonth;
new_month = next_month % 12;
if (next_month >= 12)
{
// This function has no idea is needs to redirect the out put to a file...
// its only outputting to the standard console
cout << "The next Date: " << new_month << " / ";
}
else
{
//cout << "The next Date: " << next_month << " / ";
// using the new parameter in comments
// you can now save to your file
out << /*"The next Date: " <<*/ next_month << " / "; // no I comment out your extra message since you file reading does not look for that
}
}
};
// Again we have the same general misuse of C++ ( please keep learning! hopefully I am point you in the right direction )
class Lab : public Device, public Test
{
protected:
static int n;
public:
friend istream & operator>>(istream & in, Lab & lab)
{
// Inputs
cout << "Enter Device Desciption and Serial Number: ";
getline(in, device_description);
getline(in, serial_number);
cout << "Enter Test Desciption: ";
getline(in, Test_Description);
cout << "Enter the Number of months: ";
in >> nmonth;
cout << "Enter the Most Recent Date(mm/dd/yyyy): ";
in >> recent_month >> recent_day >> recent_year;
return in;
}
friend ostream & operator<<(ostream & out, Lab & lab) {//Outputs
everything in Device Class
out << Lab::device_description << endl;
out << Lab::serial_number << endl;
out << Lab::Test_Description << endl;
// Here you should pass the output pipe
getDate(/* out */);
return out;
}
static void getN() {
cout << "Enter the number of devices: ";
cin >> n;
}
static void getWrite()
{
// there's no real need to be using a pointer or memory allocation
//Lab *obj = new Lab[n];
// you can simply use
Lab obj[n];
//if (obj == 0)
//{
// cout << "Memory Error";
// exit(1);
//}
for (int i = 0; i < n; i++)
{
cin >> obj[i];
cout << endl;
}
ofstream myfile("Device.txt");
//myfile.write((char *)obj, n * sizeof(Lab)); // I've never tried writting an object's memory as a char* to file
// usually I like to generate a human readable output
std::string objBuffer = obj.getSaveBuffer(); // you will need to implement this `getSaveBuffer()` functions
myfile << objBuffer; // This can save lots of different value types for you! see http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/
//delete[] obj; // since there is no more new; we dont need a delete!
}
// The logic of what you read suffers the same general issues as the write.
// Also what/how you read is very far from the save so I can't venture into any solutions
// I'm hoping this will kick start you to figuring it out on your own =)
static void getRead() {
ifstream file2("Device.txt");
Lab *obj2 = new Lab[n];
if (obj2 == 0) {
cout << "Memory Error";
exit(1);
}
file2.read((char *)obj2, n * sizeof(Lab));
for (int i = 0; i < n; i++) {
cout << obj2[i];
cout << endl;
}
delete[] obj2;
}
/*void getSearch(){
}*/
};
int Lab::n;
// A program that runs should always return a numeric result indicating success or failure
//void main() {
int main()
{
Lab L; // Since everything in all your classes is static this didnt really add anything
// you done need an object if the object contains nothing
L.getN();
L.getWrite();
L.getRead();
system("pause"); // this is also bad practice, see https://stackoverflow.com/a/1107717/8480874
// I personally like `getchar()` because it's easy and quick
}
it has been a few hours since I am dealing with this issue. I was wondering if someone could point out what am I doing wrong, and if possible - how to fix it. Essentially, I am simply trying to generate n number of object pairs and store them into a vector<pair<Foo, Foo>>. The algorithm involves random number generator. I use STL <random> and its components like m19937, uniform_real_distribution and uniform_int_distribution. Below is the simplified version of what I am trying to do representing the case I got at hand. The second loop always cuts short. However, I fail to see the reason why. Essentially, I never get to see the program execute completely. The last two messages never show.
program
#include <iostream>
#include <vector>
#include <random>
#include <utility>
// utility
using std::pair;
// random
using std::mt19937;
using std::uniform_int_distribution;
using std::uniform_real_distribution;
// iostream
using std::cout;
using std::endl;
// vector
using std::vector;
class Event{
private:
double x, y;
public:
Event(const double X, const double Y);
};
Event::Event(const double X, const double Y): x(X), y(Y){}
int main(){
cout << "Initializing storage..." << endl;
vector<Event> population;
vector<pair<Event,Event>> selection;
cout << "Initializing necessary member variables..." << endl;
const unsigned int SEED = 14112017;
const unsigned int MAX_ITERATIONS = 10000;
const double MIN = 1;
const double MAX = 10000;
mt19937 engine(SEED);
cout << "Generating the initial population..." << endl;
uniform_real_distribution<> real_distribution(MIN, MAX);
for(unsigned int i = 0; i < MAX_ITERATIONS; ++i){
double x = real_distribution(engine);
double y = real_distribution(engine);
Event event(x, y);
population.push_back(event);
}
cout << "Success! The initial population has been generated successfully" << endl;
population.shrink_to_fit();
cout << "Starting the selection process..." << endl;
unsigned int random = 0;
uniform_int_distribution<> int_distribution(MIN, MAX);
for(unsigned int i = 0; i < MAX_ITERATIONS; ++i){
random = int_distribution(engine);
Event event_x = population.at(random);
random = int_distribution(engine);
Event event_y = population.at(random);
pair<Event, Event> bound(event_x, event_y);
selection.push_back(bound);
}
cout << "Success! The selection process has been completed successfully" << endl;
selection.shrink_to_fit();
cout << "population size: " << population.size() << endl;
cout << "selection size: " << selection.size() << endl;
return 0;
}
I compile the above using cygwins C++ compiler, and I execute the code in command-prompt. The OS is Windows 10 x64. The box has 32 GB memory.
uniform_int_distributions constructor is as follows:
explicit uniform_int_distribution( IntType a = 0,
IntType b = std::numeric_limits<IntType>::max() );
By default, it returns an integer which covers all positive values of that type. The range includes the value of the second parameter. If it wouldn't, it would be cumbersome to specify we want all positive integers.
cppreference.com does not document it, but the C++ standard does: Thanks #Cubbi
This is documented on cppreference.com, or in the C++ standard:
26.5.8.2.1 Class template uniform_int_distribution [rand.dist.uni.int]
1 A uniform_int_distribution random number
distribution produces random integers i, a ≤ i ≤ b, distributed
according to the constant discrete probability function
[...]
// constructors and reset functions
explicit uniform_int_distribution(IntType a = 0, IntType b = numeric_limits<IntType>::max());
Here:
uniform_int_distribution<> int_distribution(MIN, MAX);
for(unsigned int i = 0; i < MAX_ITERATIONS; ++i){
random = int_distribution(engine);
Event event_x = population.at(random);
random = int_distribution(engine);
Event event_y = population.at(random);
random can take the value MAX, which is out of the bounds of the population vector.
I have been working on this for about a week and for some reason I just can't get past it. I am getting an out of range error when I am searching the elements of the array, and attempt to move the characters I need to a need array.
void showFileDateCleansed(string first[], string last[], string birthday[])
{
string tempHoldDD[10];
string tempHoldMM[10];
/*
The stuff below is working so Ijust commented it out until I figure out the isssue I am having with the dates
for (int i = 0; i < 6; i++)
{
first[i].at(0) = toupper(first[i].at(0));
last[i].at(0) = toupper(last[i].at(0));
}
for (int i = 0; i < 10; i++)
{
cout << first[i] << " ";
cout << last[i] << "\n";
}*/
int d = 0; //Im using this to keep track of whether I have passed the delimiter in the text file "-"
bool done = false;
for (int i = 0; i < 10; i++)
{
done = false;
int c = 0;//this is used for the character within the element of the array, it increments at the bottom so that it moves to the next character.
while (done != true)
{
// <TK> Check for invalid character
if (c == 0)
{
std::cout << "Invalid character at index: " << i << std::endl;
}
if (birthday[i].at(c) == '-')
{
d += 1;
done = true;
}
else
{
switch (d)
{
case 0:
{
// Try catch to prevent the out of range exception from crashing.
//try
//{
// Debug
std::cout << "C: " << c << std::endl;
// create a temporary variable for the value.
char temp = birthday[i].at(c);
tempHoldDD[i].at(c) = temp;
//}
/*catch (std::out_of_range const& exc)
{
std::cout << exc.what() << '\n';
}*/
//cout << tempHoldMM[c] << "\n";
}
case 1:
{
// Try catch to prevent the out of range exception from crashing.
try
{
// Debug
std::cout << "C: " << c << std::endl;
// create a temporary variable for the value.
char temp = tempHoldMM[i].at(c);
birthday[i].at(c) = temp;
}
catch (std::out_of_range const& exc)
{
std::cout << exc.what() << '\n';
}
//cout << tempHoldMM[c] << "\n";
c += 1;
break;
}
}
}
}
}
Your case 1 in your switch statement doesn't have a break statement, so it will fall through to case 2, where c is incremented. Could that make c get out of range too fast?
I want to repetitively solve the CG/BicGSTAB using CUSP solver, called from Fortran. To avoid transfers I am passing the Fortran data directly to CUSP. The code compiles but breaks at the run time flagging:
terminate called after throwing an instance of 'thrust::system::system_error'
what(): invalid argument
terminate called recursively
Aborted (core dumped)
Let alone the core of the code, even the print stream is not happening. The code of course is in the preliminary stage, but I wonder what is wrong with it.
extern "C" void bicgstab_(int *device_I, int *device_J, float *device_V, float *device_x, float *device_b, int *n, int *nnz){
int N = *n;
int NNZ = *nnz;
std::cout << N << " " << NNZ << " " << *device_I << std::endl;
for(int i=0; i<N;i++)std::cout << device_I[i] << " "; std::cout << std::endl;
for(int i=0; i<NNZ;i++)std::cout << device_J[i] << " "; std::cout << std::endl;
for(int i=0; i<NNZ;i++)std::cout << device_V[i] << " "; std::cout << std::endl;
for(int i=0; i<N;i++)std::cout << device_x[i] << " "; std::cout << std::endl;
for(int i=0; i<N;i++)std::cout << device_b[i] << " "; std::cout << std::endl;
// *NOTE* raw pointers must be wrapped with thrust::device_ptr!
thrust::device_ptr<int> wrapped_device_I(device_I);
thrust::device_ptr<int> wrapped_device_J(device_J);
thrust::device_ptr<float> wrapped_device_V(device_V);
thrust::device_ptr<float> wrapped_device_x(device_x);
thrust::device_ptr<float> wrapped_device_b(device_b);
// use array1d_view to wrap the individual arrays
typedef typename cusp::array1d_view< thrust::device_ptr<int> > DeviceIndexArrayView;
typedef typename cusp::array1d_view< thrust::device_ptr<float> > DeviceValueArrayView;
std::cout << wrapped_device_I[3];
/*
DeviceIndexArrayView row_indices (wrapped_device_I, wrapped_device_I + (N+1));
DeviceIndexArrayView column_indices(wrapped_device_J, wrapped_device_J + NNZ);
DeviceValueArrayView values (wrapped_device_V, wrapped_device_V + NNZ);
DeviceValueArrayView x (wrapped_device_x, wrapped_device_x + N);
DeviceValueArrayView b (wrapped_device_b, wrapped_device_b + N);
// std::cout << device_x[0] ;
// for(int i=0;i<NNZ;i++)std::cout << column_indices[i] << std::endl;
// combine the three array1d_views into a csr_matrix_view
typedef cusp::csr_matrix_view<DeviceIndexArrayView,
DeviceIndexArrayView,
DeviceValueArrayView> DeviceView;
// construct a csr_matrix_view from the array1d_views
DeviceView A(N, N, NNZ, row_indices, column_indices, values);
// set stopping criteria: // iteration_limit = 100 // relative_tolerance = 1e-5
cusp::verbose_monitor<float> monitor(b, 100, 1e-5);
// solve the linear system A * x = b with the Conjugate Gradient method
// cusp::krylov::bicgstab(A, x, b);*/
}
If this is not feasible, I can move over to another approach,but as I am not sure about the correctness, I am unable to decide. Any help is appreciated.
I have a feeling it's a stupid error, but I am making a echo server to identify packets, and output the data, then resend it back. It works on some packets, but one I'm trying to echo is breaking and saying there is a heap being corrupted.
Vector class, just using as container for now:
class vec2
{
public:
vec2(){};
float x, y;
};
PlayerData struct:
struct PlayerData
{
vec2 pos;
int health;
float rotation;
char moveflags;
short playerID;
};
Packet I'm trying to send:
struct ServerPacket_SyncGame //5
{
short packetID;
PlayerData data[8];
};
The next part is messy, but I'll comment it to try to make sense.
ServerPacket_SyncGame* SP_SG = new ServerPacket_SyncGame; //creates packet pointer
for(int i = 0; i < 8; i++) //assigns the eight playerdata structs in the packet array
{
SP_SG->data[i].playerID = i;
SP_SG->data[i].health = rand() % 30;
SP_SG->data[i].moveflags = 'D';
SP_SG->data[i].pos.x = rand() % 1000;
SP_SG->data[i].pos.y = rand() % 1000;
SP_SG->data[i].rotation = rand() % 360;
}
SP_SG->packetID = 5; //assigns the packet id
cout << "\n\nSent data: \n"; ////Outputting the data to be sent
for(int i = 0; i < 8; i++)
cout << "\nPlayer ID: " << SP_SG->data[i].playerID << "\nPosition: ("
<< SP_SG->data[i].pos.x << ", " << SP_SG->data[i].pos.y
<< ")\nHealth: " << SP_SG->data[i].health << "\nRotation: "
<<SP_SG->data[i].rotation << "\nMove Flags: "
<< SP_SG->data[i].moveflags << endl;
void* SP_SG_DAT = (void*)SP_SG; //casting the packet into a void*
char* SP_SG_BUFF = (char*)SP_SG_DAT; //casting from a void* to a char*
send(Socket, SP_SG_BUFF, sizeof(ServerPacket_SyncGame), 0); //sends the char*
char* SP_SG_RCVBUFF = new char; //new buffer for recv
recv(Socket, SP_SG_RCVBUFF, sizeof(ServerPacket_SyncGame), 0); //recv new buffer
void* SP_SG_RCVDAT = (void*) SP_SG_RCVBUFF; //casts char* to void* again
ServerPacket_SyncGame* RCVSP_SG = (ServerPacket_SyncGame*) SP_SG_RCVDAT;
//casts from void* to packet*
cout << "\n\nRecieved Data:\n\n"; //outputs converted received information
for(int i = 0; i < 8; i++)
cout << "\nPlayer ID: " << SP_SG->data[i].playerID << "\nPosition: ("
<< SP_SG->data[i].pos.x << ", " << SP_SG->data[i].pos.y
<< ")\nHealth: " << SP_SG->data[i].health << "\nRotation: "
<<SP_SG->data[i].rotation << "\nMove Flags: "
<< SP_SG->data[i].moveflags << endl;
I've used this method with other packets, and it's worked perfectly, server side this is how it echos:
for(;;)
{
char* buffer = new char;
char* temp = new char;
int size = recv(Socket, buffer, sizeof(ServerPacket_SyncGame), 0);
memcpy(temp, buffer, size);
send(Socket, (char*)InterpretInfo((void*)temp), size, 0);
};
InterpretInfo accepts the void* that you cast out of the char* you recieve, it deals with it like this:
void* InterpretInfo(void* data)
{
short* tempsht = static_cast<short*>(data);
cout << "\n\nRecieved packet ID: " << *tempsht;
switch(*tempsht)
{
This particular packet's ID is 5, this is it's case:
case 5:
//ServerPacket_SyncGame
{
cout << " which is ServerPacket_SyncGame\n";
ServerPacket_SyncGame* decoded = (ServerPacket_SyncGame*)data;
for(int i = 0; i < 8; i++)
{
cout << "Player ID: " << decoded->data[i].playerID ;
cout << "\nPosition: (" << decoded->data[i].pos.x << ", "
<< decoded->data[i].pos.y << ")\n";
cout << "Health: " << decoded->data[i].health
<< "\nRotation: " << decoded->data[i].rotation
<< "\nMove Flags: " << decoded->data[i].moveflags << endl;
}
return(void*)decoded;
}
It only does it with this packet, and it breaks and says the heap is corrupted when I try to access anything from the packet, though in debug mode I can read all information in the packet clearly.
I need at least 10 rep to post a picture, so here is a link to what I'm talking about in the running code:
http://i.imgur.com/Dbyi0c3.png
Thank you in advanced for any help or insight to help me get this done, I'm still quite novice at C++ and love to learn.
You are allocating only 1 byte for the recv() buffer, but you are trying to read sizeof(ServerPacket_SyncGame) number of bytes into it. You need to change this:
char* SP_SG_RCVBUFF = new char; //new buffer for recv
To this:
char* SP_SG_RCVBUFF = new char[sizeof(ServerPacket_SyncGame)];
Same thing with your for loop:
for(;;)
{
//char* buffer = new char;
char* buffer = new char[sizeof(ServerPacket_SyncGame)];
//char* temp = new char;
char* temp = new char[sizeof(ServerPacket_SyncGame)];
...
};
I would suggest you clean up your code:
ServerPacket_SyncGame* SP_SG = new ServerPacket_SyncGame; //creates packet pointer
for(int i = 0; i < 8; i++) //assigns the eight playerdata structs in the packet array
{
SP_SG->data[i].playerID = i;
SP_SG->data[i].health = rand() % 30;
SP_SG->data[i].moveflags = 'D';
SP_SG->data[i].pos.x = rand() % 1000;
SP_SG->data[i].pos.y = rand() % 1000;
SP_SG->data[i].rotation = rand() % 360;
}
SP_SG->packetID = 5; //assigns the packet id
...
// don't forget to do error handling on this, and pay attention to the
// return value so you know if you actually sent the entire struct or not...
send(Socket, (char*)SP_SG, sizeof(ServerPacket_SyncGame), 0);
delete SP_SG;
SP_SG = new ServerPacket_SyncGame;
// don't forget to do error handling on this, and pay attention to the
// return value so you know if you actually received the entire struct or not...
recv(Socket, (char*)SP_SG, sizeof(ServerPacket_SyncGame), 0); //recv new buffer
...
delete SP_SG;
ServerPacket_SyncGame buffer;
for(;;)
{
// don't forget to do error handling on this, and pay attention to the
// return value so you know if you actually received the entire struct or not...
int size = recv(Socket, &buffer, sizeof(ServerPacket_SyncGame), 0);
if (size > 0)
{
// don't forget to do error handling on this, and pay attention to the
// return value so you know if you actually sent the entire struct or not...
send(Socket, (char*)InterpretInfo(&buffer), size, 0);
}
};