简体   繁体   中英

C++ Allocating memory for buffer errors in free()

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM