ProtocolBuffer object ByteSize is wrong - c++

I have the following method:
void ConnectionManager::SendAll()
{
for (int t = 0; t < (int)m_Connections.size(); ++t)
{
if (m_Connections[t].socket != INVALID_SOCKET)
{
// Create the object
MessageID message;
message.set_type(MessageID::Type::MessageID_Type_PLAYERDATA);
for (int i = 0; i < (int)m_Connections.size(); ++i)
{
if (m_Connections[i].playerData.username() != google::protobuf::internal::kEmptyString)
{
auto temp = message.add_playerdata();
temp = &m_Connections[i].playerData;
}
}
if (message.playerdata_size() > 0)
{
// Serialize to byte array
int size = message.ByteSize();
void* buffer = malloc(size);
message.SerializeToArray(buffer, size);
Send(m_Connections[t].socket, buffer, size);
}
}
}
}
Now the problem lies at the end of this method, at the line:
int size = message.ByteSize();
I know that the data is loaded correctly (or it should be at least) but the size isn't right. It should be 30 and it returns 2. I have no idea what I'm doing wrong.
The data in m_Connections is available and should be reached by pointer temp. I think that, for some reason, the data is lost from the "message" object but I don't know how to solve it.

auto temp = message.add_playerdata();
temp = &m_Connections[i].playerData;
These lines look wrong. add_playerdata() returns a pointer. That means that the second line is just setting temp to some other pointer, not doing anything to the message which temp points at. It's more obvious if you write out the type rather than use auto:
MessageID::PlayerData* temp = message.add_playerdata();
temp = &m_Connections[i].playerData;
Maybe you wanted to do this instead:
*temp = m_Connections[i].playerData;
However, I do not see how this bug would lead to ByteSize() being 2. It looks like ByteSize() should only be 2 if you haven't added any players to the message, but then playerdata_size() would be zero, so you wouldn't get to the serialization step at all.

Related

Incorrect checksum for freed object - problem with allocation

I'm trying to write a class in c++ that creates a dynamic array and I'm encountering this problem
malloc: Incorrect checksum for freed object 0x7f9ff3c05aa8: probably modified after being freed.
Corrupt value: 0x2000000000000
I implemented three constructors (default, parametrized and copy) and I think this is the one causing problem because the code breaks here
CTable::CTable(string sName, int iTableLen)
{
s_name = sName;
cout<<"parametr: "<<s_name<<endl;
c_table = new int[iTableLen];
i_table_lenghth=iTableLen;
}
I also have to write a method changing the size of the array and returning true in case of the success and false in case of the failure. Maybe this method is causing the problem so this is how I implemented it.
bool CTable :: bSetNewSize(int iTableLen)
{
int size;
if(iTableLen < 0)
return false;
else if(iTableLen>=i_table_length)
size = i_table_length;
if(iTableLen < i_table_length)
size = iTableLen;
int *cTable;
cTable = new int[iTableLen];
for (int ii = 0; ii < size; ii++)
{
cTable[ii] = c_table[ii];
}
delete [] c_table;
c_table = cTable;
return true;
}
edit: The problem wasn't in any of those parts of the code. The method that was supposed to clone the object was causing the error. It happened because I allocated the object statically instead of dynamically. Here is the fixed method:
CTable* CTable::pcClone()
{
CTable *obj_clone;
obj_clone = new CTable(*this);
return obj_clone;
}
The problem is that you deleted c_table in bSetNewSize() and didn't set a new value to it, but used it in a later call. I Think you meant to put a c_table = cTable; to the end of bSetNewSize() function, as 500 - Internal Server Erro commented.
Also it is faster if you take the string parameter as a const string& to the constructor.
Edit: are you sure abaut
if(iTableLen >= 0)
return false;
This means that you actually resize only if iTableLen is negative.
Didn't you mean
if(iTableLen < 0)
return false;

Can the same structures allocate different memory sizes in C++?

My structure code is like this:
typedef struct Patterns {
int pattern_num;
char *chained_fail_log;
Patterns *next_pattern;
} Pat;
I made this structure for the linked-list, and the linked-lists are allocated by "new"
for( int num_of_pat = 1; num_of_pat < number_of_pattern+1; num_of_pat++) {
curpattern->next_pattern = new Pat;
curpattern = curpattern->next_pattern;
curpattern->next_pattern = NULL;
curpattern->pattern_num = num_of_pat;
curpattern->chained_fail_log = new char[chain_cell_length+1];
for(int i = 0; i < chain_cell_length; i++ ) curpattern->chained_fail_log[i] = '0';
curpattern->chained_fail_log[chain_cell_length] = '\0';
}
curpattern->next_pattern = NULL;
I deleted the structure by delete.
`void Circuit_Fail_Log::freepattern() {
Pat * delpattern = fail_pattern_log;
int i = 0;
while( delpattern != NULL ) {
i++;
fail_pattern_log = delpattern->next_pattern;
printf("pattern_num:%d\tchained_pattern:%s\n",delpattern->pattern_num,delpattern->chained_fail_log);
delete[] delpattern->chained_fail_log;
delpattern->chained_fail_log = NULL;
delete delpattern;
delpattern = fail_pattern_log;
}
As you see in the code, the pointer for the next list cannot point to the next list in some cases.
I assume that the memory size of the list became bigger than the size when it was allocated.
So, the linked list pointer cannot point to the next list.
error message is
*** Error in `fextraction': double free or corruption (out):0x0000000001de9de0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x81679)[0x7f66390fb679]
fextraction[0x401ae4]
fextraction[0x401ed3]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f663909c505]
fextraction[0x4008d9]
How can I fix this?
It should not happen but actually you are doing it by writing to a memory address which does not belogs to chained_fail_log.
If chained_fail_log should have chain_cell_length characters length minus the null terminator then you should :
// one more for null terminator
curpattern->chained_fail_log = new char[chain_cell_length+1];
for(int i = 0; i < chain_cell_length; i++ ) curpattern->chained_fail_log[i] = '0';
curpattern->chained_fail_log[chain_cell_length] = '\0'
In your original code curpattern->chained_fail_log[chain_cell_length] = '\0' is breaking memory boundry of your chained_fail_log
I finally find the answer.
In some cases, data was inserted in the curpattern->chained_fail_log[-1] on my program.
I fixed these cases, then the memory deallocation(delete) works without errors.

Arduino - what's a correct way to handle an array of structs?

I've got a problem while trying to fill an array with structs of Strings. Probably, I'm missing something basic in working with pointers or memory allocation rules on Arduino.
See my code below.
Data struct to be filled:
struct SMSData {
String id;
String status;
String from;
String date;
String text;
};
String parser routine:
SMSData* readSMS(String reply) {
debugSerial.println(reply);
// declare a pointer to result array
SMSData* smsArray = NULL;
const String startPattern = F("+CMGL: ");
int index = -1;
// calculate result array length
byte count = 0;
do {
index = reply.indexOf(startPattern, (index + 1));
if(index < 0) {
break;
}
count++;
} while(true);
if(count == 0) {
return NULL;
}
debugSerial.println(count);
// allocate memory to store result array
smsArray = malloc(count * sizeof(SMSData*));
if(smsArray == NULL) {
return NULL;
}
// start parsing input String
index = reply.indexOf(startPattern);
int fromIndex = 0;
while(true) {
debugSerial.println();
if(index < 0) {
break;
}
// init data for the next element of result array
SMSData smsData = {"", "", "", "", ""};
// start filling result array element
// get id
fromIndex = index + startPattern.length();
index = reply.indexOf(F(","), fromIndex);
smsData.id = reply.substring(fromIndex, index);
debugSerial.println(smsData.id);
// get status
fromIndex = reply.indexOf(F("\""), index) + 1;
index = reply.indexOf(F("\""), fromIndex);
smsData.status = reply.substring(fromIndex, index);
debugSerial.println(smsData.status);
// get phone
fromIndex = reply.indexOf(F("\""), index + 1) + 1;
index = reply.indexOf(F("\""), fromIndex);
smsData.from = reply.substring(fromIndex, index);
debugSerial.println(smsData.from);
// get date
fromIndex = reply.indexOf(F("\""), index + 1) + 1;
index = reply.indexOf(F("\""), fromIndex);
smsData.date = reply.substring(fromIndex, index);
debugSerial.println(smsData.date);
// get text
fromIndex = index + 1;
index = reply.indexOf(startPattern, fromIndex);
if(index < 0) {
smsData.text = reply.substring(fromIndex);
} else {
smsData.text = reply.substring(fromIndex, index);
}
smsData.text.trim();
debugSerial.println(smsData.text);
// add filled element to result array
smsArray[count - 1] = smsData;
}
return smsArray;
}
Output parsed data:
SMSData* smsArray = readSMS(reply);
int count = sizeof(smsArray);
debugSerial.print(F("SMS count:"));
debugSerial.println(count);
for(int i = 0; i < count; i++) {
SMSData smsData = smsArray[i];
debugSerial.print(F("id: "));
debugSerial.println(smsData.id);
debugSerial.print(F("status: "));
debugSerial.println(smsData.status);
debugSerial.print(F("from: "));
debugSerial.println(smsData.from);
debugSerial.print(F("date: "));
debugSerial.println(smsData.date);
debugSerial.print(F("text: "));
debugSerial.println(smsData.text);
}
free(smsArray);
Dummy String to parse:
String reply = "+CMGL: 1,\"REC READ\",\"+123456789012\",,\"2017/09/26,18:31:25+03\"\r\nHi\r\n+CMGL: 2,\"REC READ\",\"+123456789012\",,\"2017/09/26,18:34:25+03\"\r\nHello\r\n";
When I run the sketch it's output is often different, but always broken and incomplete, e.g.
+CMGL: 1,"REC READ","+123456789012",,"2017/09/26,18:31:25+03"
Hi
+CMGL: 2,"REC READ","+123456789012",,"2017/09/26,18:34:25+03"
Hello
2
1
REC READ
+12345678905+03 017/09/26,18:31:25+03
Hi
2
REC REA
As you can see according to the output, it logs out the whole input string, starts parsing it, goes through the first loop iteration (mixing strings from struct fields), starts the second iteration filling struct with heavily mixed Strings once again and then stops responding in the middle of it.
Right now I see no reason for such behaviour except the problems with memory allocation, but I can't find out what I'm doing wrong.
Any your help is appreciated.
First, your code is c++, not strictly c, that's okay, but the tag should be changed. Here are some problems I found in your code...
///// Passing nothing, println requires one or two parameters
debugSerial.println();
See documentation on println
// init data for the next element of result array
////// You are creating a local buffer, it will go out of scope
////// when you leave the function. And you are trying to store
////// it in an array that you return from your function.
////// And you are changing the data with pass through your loop
////// (2 passes).
SMSData smsData = {"", "", "", "", ""};
//...
////// You should be assigning an allocated struct pointer
////// count is not changing, you are only assigning the last
////// element of the array.
smsArray[count - 1] = smsData;
///// This will not work. smsArray is a pointer and you have lost
///// the information about how much memory was allocated and assigned to
///// the pointer.
SMSData* smsArray = readSMS(reply);
int count = sizeof(smsArray);
One trick we use to use with C style pointers as arrays, was to allocate a block of pointers one bigger than we needed, and make sure they were all set to NULL (using calloc() instead of malloc()). Then, we would set eacch pointer in the array except the last one. Finally, we would iterate through the array until the pointer was NULL, indicating the end of the data.
You should be storing pointers to allocated data in your smsArray, and you should free (destroy) the that data as well as the array.
So, your code might look something like...
SMSData** smsArray = NULL;
smsArray = (SMSData **)calloc(count+1, sizeof(SMSData *));
int idx = 0;
//...
SMSData* smsData = new smsData();
smsData->id = ""; //etc. for the rest of the fields
//...
smsArray[idx++] = smsData;
//..
After return...
SMSData ** smsArray = readSMS(reply);
SMSData ** ptr = smsArray;
while (ptr != NULL) {
//do stuff with ptr->whatever
destroy(ptr); //destroy since allocated with new
ptr++;
}
free(smsArray); //free since allocated with malloc
This is not the best code (and may have bugs, I don't have access to my compiler right now). But it tries to stick with your approach.

An issue with memory allocations of arrays of the same size

I'm having a weird behaviour with my C++ code. Here it is.
OI_Id * Reqlist = 0;
int * Idlist = 0;
int Reqsize = listcount; // we calculate listcount somehow earlier.
Idlist = new int [Reqsize];
if (Idlist == 0)
{
return;
}
printf ("Idlist = %0x",Idlist);
Reqlist = new OI_Id [Reqsize]; // OI_Id is a 3rd party lib simple struct.
if (Reqlist == 0)
{
return;
}
printf ("Reqlist = %0x",Reqlist);
So the problem is that in both cases it prints the same value - the same pointer is returned by the new operator. BUT! If we change the length of second allocated array to another value (Reqsize+ 1, for example), everything is OK.
Did anybody meet any similar behaviour? I have no idea what's the reason of the problem.

Resizable Array with pointers

My program works but my professor says that my code is incorrect but stated that he will get to why in the fall term... What is he talking about?
perhaps something is improper? Even if you are incorrect I would appreciate picking your brain :)
void CResizableArray::SetSize( int intNewSize )
{
int intIndex = 0;
if( intNewSize < 0 ) intNewSize = 0;
if( intNewSize > intMAXIMUM_ARRAY_SIZE )
{
intNewSize = intMAXIMUM_ARRAY_SIZE;
}
//////////////////////////////////////
// ---> HUGE BUG HERE <--- //
// Code works but is WRONG //
// WHY IS THIS HELP ME FIND THE BUG //
//////////////////////////////////////
m_intArraySize = intNewSize;
m_paintValues = new int [m_intArraySize];
// Initialize to zero
for( intIndex = 0; intIndex < m_intArraySize; intIndex++ )
{
*( m_paintValues + intIndex ) = 0;
}
}
Presumably before this line
m_paintValues = new int [m_intArraySize];
m_paintValues pointed to another array. That array has now been leaked -- you don't have a pointer to it, so it can never be freed. That memory can therefore never be reused. Write a program that does a lot of this, and it'll run out of memory before running very long.
When you're through with a block of memory, you need to free it. Here, the proper thing to do might look something like
delete[] m_paintValues;
m_paintValues = new int [m_intArraySize];
There are more issues, though. First of all, you can never use delete[] unless you know that m_paintValues definitely points to an array; you could ensure that in the constructor. More troubling is that fact that when you set a new size, any data previously in m_paintValues is discarded -- don't you want to copy the old values into the new array? Doing so would mean using a temporary variable to hold the new array when first allocated, copying the data, and then assigning the new array to the member variable.
He may mean that since it is a resize you should keep the old contents of the array and transfer them over to the new array, in your snippet you just throw away the old content creating a new empty array.
so instead of
m_paintValues = new int [m_intArraySize];
// Initialize to zero
for( intIndex = 0; intIndex < m_intArraySize; intIndex++ )
{
*( m_paintValues + intIndex ) = 0;
}
do
int* newBiggerArray = new int[m_intArraySize];
for (intIndex = 0; intIndex < m_intArraySize; ++intSize)
{
if ( intIndex < oldMaxSize )
{
newBiggerArray[intIndex] = m_paintValues[intIndex];
}
else
{
newBiggerArray[intIndex] = 0;
}
}
delete [] m_paintValues;
m_paintValues = newBiggerArray;
I will leave the part to handle a resize to a smaller value than previous for you to figure out.