I'm using Arduino Uno to save several variables into the EEPROM. My solution to this is to create a custom struct in which to store all the variables needed then use EEPROM.put to store them into the built-in EEPROM.
My problem arises not when putting data, but when getting data. Whenever I would change something in my code and/or use the Arduino in a short amount of time, the data stored in the EEPROM gets corrupted.
I check the data through Serial.println() function. From time to time the String data get corrupted but not the other data types as far as I can remember. Maybe an issue with String data?
struct EEPROMDATA
{
String customMessage, emergencyMessage;
String emergencyContact[3];
String ownerContact;
String idleMessage;
int travelThreshold;
int idleThreshold;
char password[6];
location locationList[3];
};
EEPROMDATA eepromstruct;
void loadReset()
{
EEPROM.get(100, eepromstruct);
}
void saveReset()
{
EEPROM.put(100, eepromstruct);
}
These are the functions I use to save (put) and load (get) the data from the EEPROM. I've read somewhere to avoid writing data at the 0th address that's why the address is set to 100.
Do remember that this is not a writing to EEPROM issue as my program currently doesn't have any references to EEPROM.put nor to saveReset(). Somehow during the course of the program the EEPROM data gets corrupted. I don't know if this is a hardware or a software problem.
EDIT: I forgot to note that when troubleshooting this, whenever a corruption occurs, I re-initialize then save the data in the EEPROM again. After that it works fine for a short while (turning on/off continuously then testing the data, resetting the device, etc.) until it corrupts again.
You need to use char[] instead of using String which is a class object when you declare at some point in your code. The object (an instance of the class) is supposed to refer the other area of the memory in case of dynamic memory allocation to store its data by its methods. Even though you're assuming that your data would be stored in EEPROM, but actually, it was stored in some area of RAM. That's why you have corrupted data only with String data.
First of all, if you change the definition of class EEPROMDATA, this will "corrupt" your eeprom data. Not in the sense that the data in the eeprom is somehow changed, but in the sense that you're trying to read data written in an old format into a new format.
Next, strings are variable size char arrays. Structs assume a static memory layout. The String class achieves variable length storage through indirection (pointers, essentially), which cannot be trivially translated from RAM to EEPROM.
You need to decide whether you want static layout in EEPROM (in which case you have to stop messing with the struct, and dedicate a specific number of chars to your strings) or dynamic (in which case you need to write an "intelligent" function to parse the data into/out of EEPROM)
Related
I'm trying to optimize some code I've written to handle several layers of an application protocol. I made liberal use of the std::string class, and strove for simplicity rather than premature optimization. The application is too slow, and valgrind & gprof show I'm spending significant time copy-constructing strings as a buffer moves upward through my stack.
It seems to me that, after copying chars from the system buffer to my lowest application buffer, I should be able to avoid copying the data any more: after all, it is not mutated as it moves up the stack.
My protocol format is a "transmission", consisting of one or more newline-terminated records, each consisting of several tab-separated fields, and terminated with a special token. E.g.
RECORD 1\tHAS\tTHESE\tFIELDS\nRECORD 2\tLOOKS\tLIKE\tTHIS\nEND-OF-TRANSMISSION\n
This would be assembled in a single std::string called input_buffer.
The processing of a transmission involves extracting a record from the buffer and passing it to the next layer; extracting a vector of fields from the record and passing it to the next layer; storing the fields into a map. At each stage, data is being copied as new std::strings are allocated.
Is it possible to allocate a const string from an index into input_buffer, and a length ... without any copying being done? For example, RECORD 2 begins at offset 26 and is 24 chars long:
const std:string record (substr(input_buffer, 26), 24 );
I'm not familiar with the innards of a string object, but its performance guarantees seem to imply that somewhere there's a simple char sequence, and almost undoubtedly a pointer to those chars' memory. Could that pointer be initialized to memory belonging to another string?
(My compiler is g++ 4.7, but if this is something that requires 4.8, I'd appreciate knowing about that too.)
From what I understand, this sounds like a good candidate for boost::string_ref.
You would simply do boost::string_ref input(input_buffer); and then pass string_refs up the stack instead. The only thing you have to worry about is keeping the original buffer alive the whole time.
I am a beginning C++ student. I have a structure array that holds employee info.
I can put values into the structure, write those values to a binary dat file and
read the values back into the program so that it can be displayed to the console.
Here is my problem. Once I close the program, I can't get the file to read the data from the file back into memory - instead it reads "garbage."
I tried a few things and then read this in my book:
NOTE: Structures containing pointers cannot be correctly stored to
disk using the techniques of this section. This is because if the
structure is read into memory on a subsequent run of the program, it
cannot be guaranteed that all program variables will be at the same
memory locations.
I am pretty sure this is what is going on when I try to open a .dat file with previously stored information and try to read it into a structure array.
I can send my code examples if that would help clarify my question.
Any suggestions would be appreciated.
Speaking generally (since I don't have your code) there's two reasons you generally shouldn't just write the bytes of a struct or class to a file:
As your book mentioned, writing a pointer to disk is pointless, since you're just storing a random address and not the data at that address. You need to write out the data itself.
You especially should not attempt to write a struct/class all at once with something like
fwrite(file, myStruct, sizeof(myStruct)). Compilers sometimes put empty bytes between variables in structs in order to let the processor read them faster - this is called padding. Using a different compiler or compiling for a different computer architecture can pad structures differently, so a file that opens correctly on one computer might not open correctly on another.
There's lots of ways you can write out data to a file, be it in a binary format or in some human-readable format like XML. Regardless of what method you choose to use (each has strengths and weaknesses), every one of them involves writing each piece of data you care to save one by one, then reading them back in one by one. Higher level languages like Java or C# have ways to do this automagically by storing metadata about objects, but this comes at the cost of more memory usage and slower program execution.
My program uses UDP to send data between two programs, it works great however I have added a new vector into the data I want to send, the vector type is another class which looks like this...
class Bullet: public Sprite
{
public:
float speed;
};
The DataPacket...
typedef struct DataPacket
{
int ID; //Player ID
int elapsedTime; //Total elapsed player time
float x, y; //X & Y pos of player
std::vector<Bullet>* pBullets; //Vector containing all the players bullets
};
Is there a way to send this data correctly? The expression cannot be evaluated once the server receives the data from the client, every other part is correct in the received packet.
Basically the server is receiving the positional data of the bullets on the screen which is contained in this Bullet class along with a few other items.
Just to note: pBullet never used to be a pointer but in an attempt to try and figure out what was wrong I changed it to a pointer...it never fixed the issue tho
You cannot do this. A vector is a class which is typically implemented with an internal pointer to dynamic memory which changes location as the vector grows.
When you try and serialize the vector by casting your whole structure, you just serialize the pointer to the memory holding the vector contents, you don't get the contents itself because it's not part of that structure.
You'll have to individually serialize all items in the vector one-by-one and individually add them back in when you deserialize it.
Note that you can change the vector of bullets to a statically sized array internal to the structure and then it would be contiguous in memory and you could just serialize the whole structure - and you can also make the last element of the array an array of one bullet, and then allocate memory for the structure size + (x-1)*sizeof(Bullet), allowing you to overwrite the array of 1 for all of the extra memory you added. This would also be contiguous in memory allowing you to serialize the whole memory region pretty easily.
You should also look in to htonl, ntohl, htons, ntohs and start network-byte-ordering your data as well if you're going to send it over a network to keep the byte endianness from being an issue on some other systems you might end up using.
Use Serialization whenever you have to send data across the network. You may refer to Boost Serialization.
Your DataPacket is something whose size is dynamic. Had it been an array than vector, it might have worked given the same endianness of the machines.
For Game Development I would recommend to use Google ProtoBuf. In comparison with Boost Serialization, it provides binary serialization (Boost Serialization has an example of binary serialization but it's not very portable) and is more convenient for complex data structures.
You need to serialize the data yourself. You can't just send std::vector or pointer thereto.
Now I have a database, which one field type is an array of byte.
Now I have a piece of memory, or an object. How to convert this piece of memory or even an object to a byte array and so that I can store the byte array to the database.
Suppose the object is
Foo foo
The memory is
buf (actually, don't know how to declare it yet)
The database field is
byte data[256]
Only hex value like x'1' can be insert into the field.
Thanks so much!
There are two methods.
One is simple but has serious limitations. You can write the memory image of the Foo object. The drawback is that if you ever change the compiler or the structure of Foo then all your data may no longer loadable (because the image no longer matches the object). To do this simply use
&Foo
as the byte array.
The other method is called 'serialization'. It can be used if the object changes
but adds a lot of space to encode the information. If you only have 256 bytes then you
need to be watchful serialization doesn't create a string too large to save.
Boost has a serialization library you may want to look at, though you'll need to careful about the size of the objects created. If you're only doing this with a small set of classes, you may want to write the marshalling and unmarshalling functions yourself.
From the documentation:
"Here, we use the term "serialization" to mean the reversible deconstruction of an arbitrary set of C++ data structures to a sequence of bytes. "
I'm using C++ and wondering if I can just send an entire int array over a network (using basic sockets) without doing anything. Or do I have to split the data up and send it one at a time?
Yes.
An array will be laid out sequentially in memory so you are free to do this. Simply pass in the address of the first element and the amount of data and you'll send all data.
You could definitely send an array in one send, however you might want to do some additional work. There are issues with interpreting it correctly at the receiving end. For example, if using different machine architectures, you may want to convert the integers to network order (e.g., htonl).
Another thing to keep in mind is the memory layout. If it is a simple array of integers, then it would be contiguous in memory and a single send could successfully capture all the data. If, though, (and this is probably obvious), you have an array with other data, then the layout definitely needs consideration. A simple example would be if the array had pointers to other data such as a character string, then a send of the array would be sending pointers (and not data) and would be meaningless to the receiver.