I'm having a bad time with writing and reading from binary files in C++.
I learned a lot from stack questions, but I never got it working and i'm guessing that problem resides in the reading process,
Here are the read and save methods:
void date::save(ofstream& fo){
fo.write((char *) &jour, sizeof(int));
fo.write((char *)&moi, sizeof(int));
fo.write((char *)&annee, sizeof(int));
size_t len = heure.size();
fo.write((char *)&len,sizeof(size_t));
fo.write(heure.c_str(), heure.size());
}
void date::load(ifstream& fi){
fi.read((char *)&jour, sizeof(int));
fi.read((char *)&moi, sizeof(int));
fi.read((char *)&annee, sizeof(int));
size_t len;
fi.read((char *)&len, sizeof(size_t));
char* temp = new char[len+1];
fi.read(temp, len);
temp[len] = '\0';
heure = temp;
delete [] temp;
}
In additon: Is it possible to save classes with dynamic attributes directly with ofstream.write() functionality?
Many thanks.
The reading and writing seems to be correct on first sight, when assigning
heure = temp;
there is a problem.
you allocate len+1 bytes of memory. temp points to the beginning of that memory.
after your assignment (heure = temp) heure also points to that same memory. Then you call delete and from that point, any other operation may write any data to that memory (refered to as 'wild pointer').
You have to use
strcpy(heure, temp);
to copy each byte from temp to the memory that is allocated by heure. make sure of course that heure has allocated enough space to fit all the bytes of temp.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am trying to read a .txt file and print the lines, while using only c-style string.
int main(int argc, char * argv[]){
...
size_t size = 2;
char* line = new char[size];
char c;
while (file.get(c)) {
if(c != '\n'){
line[size - 2] = c;
char* temp = new char[size + 1];
memcpy(temp, line, size * sizeof(char));
delete[] line;
line = temp;
delete[] temp;
size++;
} else{
line[size - 1] = '\n';
cout << line << endl;
delete [] line;
size = 2;
line = new char[size];
}
}
...
}
I am getting the error free(): double free detected in tcache 2. What is the problem and how can fix it?
I am getting the error free(): double free detected in tcache 2. What
is the problem and how can fix it?
By understanding the error in this code:
char* temp = new char[size + 1];
memcpy(temp, line, size * sizeof(char));
delete[] line;
line = temp;
delete[] temp;
The important thing to remember is that temp and line are pointers to an array of chars; that is they can refer to an array but they do not (by themselves) represent copies of the array. So:
// sets (line) to a memory address where (size) bytes have been
// made available for you to use. Let's assume (line) gets set to
// 0x11223344
char* line = new char[size];
[...]
// sets (temp) to the memory address where (size+1) bytes have been
// made available for you to use. For the sake of the exmaple,
// let's assume (temp) gets set here to memory-address 0x12345678.
char* temp = new char[size + 1];
// Copies (size) bytes from (line) (aka starting at memory-address 0x11223344)
// to (temp) (aka starting at memory-address 0x12345678)
memcpy(temp, line, size * sizeof(char));
// tells the heap that you no longer need the byte-array starting at 0x11223344.
// After this delete[] returns, the heap is allowed to reuse those
// bytes for other (unrelated) things, so you are no longer allowed to
// read or write that memory region!
delete[] line;
// Sets the value of the (line) pointer to point to 0x12345678 instead.
line = temp;
// tells the heap that you no longer need the bytes starting at 0x12345678.
// After this delete[] returns, the heap is allowed to use those
// bytes for other (unrelated) things, so you are no longer allowed to
// read or write that memory region!
delete[] temp;
// Note that at this point, (line) is still pointing to 0x1234568, *but*
// you are no longer allowed to use the memory at that address!
// This is a problem, because on the next iteration of your while-loop,
// you are going to write to either line[size-2] or line[size-1]; either
// either way you are writing to freed memory, which will invoke
// undefined behavior and cause problems for you.
So, how to fix this? As suggested in the comments, the best way to fix it would be to avoid new and delete[] entirely, and stick to using std::string instead, since that would avoid all the usual problems with dangling pointers, use-after-free, uninitialized-memory-reads, unterminated strings, etc.
If you must use new and delete[], however (e.g. because that's the rules of the assignment), then you need to keep track of the lifetime of each of your heap allocations; in this case, that means realizing that when you set line = temp;, that means that line is now pointing to the same array temp is pointing to, and since your code wants to use that array in the future, you shouldn't call delete[] temp; as that deletes the heap-allocation that line was pointing to, and leaves line as a dangling-pointer (i.e. pointing to memory you are no longer permitted to use).
I get this error :
"crt detected that the application wrote to memory after end of heap
buffer"
this program should write every second sign...
char x = 1;
while ( x != 0) {
char *ptr(0);
ptr = new char;
fgets(ptr, 100001, stdin);
for (char i = 0; i < sizeof(ptr); i++) {
cout << *(ptr + i);
i++;
}
cout << endl;
delete ptr;
ptr = 0;
}
ptr = new char; allocates exactly one byte for the pointer. Than fgets(ptr, 100001, stdin); attempts to read up to 100001 characters into it, obviously well beyond it's allocated boundary.
The immediate solution would be to make sure you allocate the buffer with adequate size using array form of new, i.e. ptr = new char[100001];. This, in turn, will lead to changing the delete into it's array form as well: delete[] ptr
Also, keep in mind that sizeof(ptr) will give you the size of the pointer (4 or 8 bytes on most platforms). You would want to use strlen or similar to find out when the string ends.
All suggestions above should be taken in light of the learning exercise. In real life, you should not do this, and instead use std::string and modern ways of string-oriented reading. (std::getline would be the most readily available).
sizeof returns size in bytes of the object representation of type. https://en.cppreference.com/w/cpp/language/sizeof
One other point major point to note is that ptr = new char will only allocate exactly one byte from the heap. But in your code you are trying to read 100001 bytes and obviously this is beyond the accessible memory range of that pointer.
you can modify the error as ptr = new char[100001]; When you do this, there is another change that you must do in order to avoid memory leaks.
That being, delete[] ptr. Because you have allocated 100001 adjacent bytes, you have to de-allocate them all.
Ok, i remade my question a bit, i do not understand how TO properly deflate the content into the DYNAMIC buffer, who needs to be constantly reallocating. I re-wrote my code a bit, and it work ONLY if no reallocating of the buffer happens, so on the small amount of data, reallocating breaks somehow the output stream.
void test_deflate_dynamic(char*str)
{
if(store == NULL) // first call to the function allocate some memory etc
{
gzip_stream.zalloc = Z_NULL;
gzip_stream.zfree = Z_NULL;
gzip_stream.opaque = Z_NULL;
result = deflateInit(&gzip_stream,9);
if(result!=Z_OK) { printf("bad\r\n"); exit(0); }
total_buf_size =deflateBound(&gzip_stream,strlen(str));
printf("d_bound_init=%d\r\n",total_buf_size);
store = realloc(store,total_buf_size); // first allocation
gzip_stream.avail_out = total_buf_size;
gzip_stream.next_out = store;
gzip_stream.avail_in = strlen(str)+1;
gzip_stream.next_in = str;
result = deflate(&gzip_stream,Z_NO_FLUSH);
}
else
{
gzip_stream.avail_in = strlen(str)+1;
gzip_stream.next_in = str;
int t_size;
printf ("avail_out=%d\r\n",gzip_stream.avail_out);
t_size = deflateBound(&gzip_stream,strlen(str));
printf("d_bound=%d\r\n",t_size);
total_buf_size += t_size;
gzip_stream.avail_out = total_buf_size;
store = realloc(store,total_buf_size);
gzip_stream.next_out = store;
result = deflate(&gzip_stream,Z_NO_FLUSH);
}
}
As you can see i'm using the function deflateBound to detect how much more data i need to allocate, so first, is it correct to use deflateBound? Second, is the pointer which modified by realloc and then re-assigned to the z_stream, still points to the beginning of the data? So basically if i'm using multiple reallocations the end data is broken. End: How do i proper detect, how much data do i need to allocate for my output deflate buffer, and is it correct to use the dynamic re-allocating buffer in the z_stream?
realloc ensures the data is copied to the new location when the new size didn't fit into the old memory position. calloc just zeros the allocated memory, and doesn't copy over the old data. Therefore you must pass bigger values to calloc. You probably only need one call to calloc when you pass it that big numbers whereas realloc can accept smaller increments. Make sense?
Cheers
How to copy a matrix into where a pointer points to?
I am new in c++. I tried a lot but I could not find any solution.
here is my code:
float *output = new float[HighRange];
output = new float[10 * 10];
for(int i=0; i<10; i++){
for(int j=0; j<10; j++){
output[j]=input[i][j]; ---> I have error in this line
Thanks in advance
There are several ways to arrange the elements of input in output. Here is one way:
output[i*10 + j] = input[i][j]
Aside from NPEs suggestion, you have a memory leak here:
float *output = new float[HighRange]; // allocate contiguous block HighRange * sizeof(float) bytes
output = new float[10 * 10]; // allocate contiguous block 100 * sizeof(float) bytes
Aside from this being unnecessary, you leak memory, i.e. you allocate storage in the first statement that you never free before assigning a new value to the pointer that hold the first address to the previously allocated storage.
When allocating memory dynamically using new, you need to make sure you delete it accordingly. For arrays, you need to do the following:
float *output = new float[HighRange]; // allocate
delete [] output; // deallocate, note the delete[] operator
output = new float[10 * 10]; // allocate anew
Note: This is just to display correct usage of new/delete[]. By no means do I suggest your code would be any better if you handled deallocation in your example. :)
It seems that following code is leaking memory. I checked the JVM memory utilization and it is not freeing up memory after subsequent calls. When I just run the Java as standalone it works fine for multiple calls and keeps deallocating memory just fine.
I would really appreciate any help.
jobjectArray my_obj = (jobjectArray) env->CallObjectMethod(cls, mid, qstr, pstr);
length = env->GetArrayLength(my_obj);
//printf("\nArray Length = %d \n", length);
char result[256];
const char *cstr;
int numberOfCharsInThisRow = 0;
array1 = (char **)malloc(length * sizeof(char *));
/*Check if pointer is null, if not then free its memory first*/
for(int i=0; i< length ; i++){
cstr = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(my_obj,i), 0);
numberOfCharsInThisRow = std::strlen(cstr)+1;
*(array1+i)=(char *)malloc(numberOfCharsInThisRow * sizeof(char));
std::strcpy(result, cstr);
std::strcpy(*(array1+i),result);
env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(my_obj,i), cstr);
}
env->DeleteLocalRef(my_obj);
}
//printf("\n\nDestroy JVM\n\n");
//jvm->DestroyJavaVM();
}
void libdeallocatememory(char **array1,int length)
{
//printf("Free Array memory \n");
for (int j=0 ;j <length ;j ++)
{
free(array1+j);
}
free(array1);
}
You should free the array1 pointers once you are done with them. What does this function do in reality? From the functionality I understood, you are copying from the java to a c pointer. What happens next? By calling ReleaseStringUTF, you are notifying the JVM that it isnt being used in native and so can be GCed when required
Think I have found the problem. Releasing Code should be something like
for (int j=0 ;j<length; j++ )
{
free(array1[j]);
}
free(array1);
The initial allocation should be array1 = (char **)malloc(length * sizeof(int *));
The difference is int* instead of char*. This is because this array is just an array of pointers. Pointer size is int. The next level is in the loop where you allocate memory for your strings. It should be array1[i] = (char *)malloc(numberOfCharsInThisRow * sizeof(char));
That means initially you allocated an array of pointers. Now for each element of that arary, you are allocating the memory to hold its own string. I think even *(array1+i) will work, but I find this more easy to read. So when you free, first you free the individual array elements you allocated, and then the entire array which you allocated initially. As an example, take a look at your current deallocate function. There is no difference between the free when j=0 and the last free. I am surprised you are not getting any crashes.
Take a look at http://c-faq.com/~scs/cclass/int/sx9b.html
Also try the following jstring myString =env->GetObjectArrayElement(my_obj,i); Use myString to get the UTFChars, Then call env->ReleaseStringUTFChars(mystring, cstr)