I need to store some tuples of this data into a buffer.
"1444394028","1","5339","M","873"
"1444394028","1","7045","V","0.34902"
"1444394028","1","7042","M","2"
"1444394028","1","7077","V","0.0470588"
"1444394028","1","5415","M","40"
As you can see, the length of the records varies. One line equals one record. I've written this function:
std::string data_string = (record.asString());
char* data = (char*) malloc (data_string.length() );
std::copy( data_string.begin(), data_string.end(), data );
data[data_string.length()] = 0;
ressourceBuffer.push_back(data);
Now I can work with the buffer fairly well, but if I want to free the memory, I run into errors. My free function looks like this:
/* free memory */
for (const char* b : ressourceBuffer) {
free ((char*) b);
}
I really can't find a solution and am running out of ideas. It creates this error (these are the first lines from about 50 in the stacktrace):
*** Error in `./build-debug/bin/Test': free(): invalid next
size (fast): 0x00000000019b3cb0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7da1389d97e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7da1389e237a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7da1389e653c]
First of all, as already said in comments you should rather not use malloc
in C++; there are implications of it not being considered by the standard in several regards, which can make it painful to use. Use new
, or, preferably, standard containers. Also use static_cast
and companions over C-style casts.
Second:
data[data_string.length()] = 0;
writes one past the end of the buffer. Let N
be data_string.length()
char* data = (char*) malloc (data_string.length() );
allocates N
bytes, with indexes 0
to N - 1
being in the allocated memory. N
is therefor outside of the allocated memory. I cannot guarantee to you that this is your problem, though.
Which brings me to third: post a minimum complete example please. The snippets you provide are not sufficient to really tell what's going on. What is ressourceBuffer
, and what is resource
for example.
You should model the text lines as a structure:
struct Record
{
std::string field1; // Rename with column name
std::string field2;
std::string field3;
std::string field4;
}
Next, overload operator>>
to read in the record:
struct Record
{
//...
friend std::istream& operator>>(std::istream& input, Record& r);
};
std::istream& operator>>(std::istream& input, Record& r)
{
// Read column data until the ',' but don't put ',' into string.
std::getline(input, r.field1, ',');
std::getline(input, r.field2, ',');
std::getline(input, r.field3, ',');
std::getline(input, r.field4);
}
The above allows you to create a database using std::vector
and simplify reading of the file:
std::vector<Record> database;
Record r;
while (my_data_file >> r)
{
database.push_back(r);
}
The above will simplify the database creation.
Also, the above code allows you to handle variable length records.
By using std::vector
, you don't need to concern yourself about malloc
, free
, new
or delete
. The std::vector
handles memory allocation so you don't need to.
Later, you may want to change the operator>>
method to read numeric fields as numbers and remove the "
from the strings (see std::string::find
and std::string::erase
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.