I've a fread line in my code that reads the contents of the file like this
fread(buffer,sizeof(char),1024,file1);
I kow that I can free the buffer using free(buffer); but my questions is, is there a way to delete the elements in the buffer one by one?. Say, I used the first element and I no longer need it so I want to delete it.
Something which might do like this
for(i=0 ; i< 1024; i++){
*do something with buffer[1] *
free(buffer[1]); // I know this is wrong but something which can do the same.
}
Thanks,
sunil
The buffer has to be freed the same way it as allocated, in one shot. You asked for a contiguous block of memory, which is returned to you prefaced by heap control info describing the buffer as such. If you were to try to free elements individually the heap manager would get confused and the process fault.
No, there is no way to do this. Just store the original pointer somewhere, and increment the pointer you're working with. When you're done, you can feel free to free the original pointer.
That said, if you are using C++, you shouldn't be using malloc or free at all, nor should you be using fread ....
If you want to break up your allocation/file read into smaller values, you could do it. Like Steve said, though, you can only deallocate the exact same chunks of memory you allocate.
An example of changing your existing code:
const size_t size_of_full_buffer = 1024;
const size_t size_of_buffer_chunk = 128; /* evenly divisible */
size_t size_read = 0;
while(size_read <= size_of_full_buffer)
{
buffer = (char*) malloc(sizeof(char) * size_of_buffer_chunk)
fread(buffer, sizeof(char), size_of_buffer_chunk, file1);
for(i = 0; i < size_of_buffer_chunk; i++)
{
/* do something with buffer[1] */
}
free(buffer);
size_read += size_of_buffer_chunk;
}
However, you should use an input file stream instead of fread. If file streams require you to allocate a buffer (they might not) use a vector instead of malloc/free.
std::fstream, std::ifstream
std::vector
You can free only what you allocated. What you allocated is the whole buffer and not the individual elements of the buffer.
From N1256 (I don't have the C99 standard with me)
$7.20.3.2/2- "The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or 261) realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
If you are however looking at removing unnecessary elements read from the buffer, you will have to either do it yourself if you are using arrays, or you will have to settle in for STL containers (vector/list) etc (which provide interfaces for element management)
A C++ stl way of doing this would be
#include <fstream>
#include <cassert>
#include <vector>
void foo () {
const char* myFilename = "some_file_path";
std::ifstream myStream (myFilename);
assert (myStream.is_open());
int n = 1024;
std::vector<char> buffer (n);
myStream.read (&buffer[0], n);
assert (myStream.good());
for (int i = 0; i < n; i++) {
char* myPtr = &buffer[i];
//do something with buffer[i]
}
}
Related
i want to take a simple array of string from the user in a dynamic array. If i made the size of the array 1000 for example. how to delete the unused space in the array so that it fits just for the size the user entered without deleting the whole array?
Memory allocators do not typically allow for deallocating parts of allocated memory, and the allocation facilities specified in C++ certainly do not provide any interface to such functionality.
There is a standard function 'realloc' which may allow an allocated block of memory to be, apparently, expanded. However the way this typically works is that the underlying allocator checks to see if previously allocated block of memory is already large enough. That is, when you allocate, say, 1000 bytes, the allocator may provide a chunk of memory that is larger than 1000 bytes.
That hidden 'extra' memory is valid to access just as if you had asked for it, but since you didn't ask for it and don't know how much, if any, extra memory is there, you are limited to only accessing the bytes you actually requested.
realloc will provide to you allocated memory of the new size, with the same contents as the memory pointed to by the parameter you pass to it. It may do this by discovering that the existing block of memory is large enough for the requested new size, in which case it simply returns the same pointer you pass to it. In this case you know there was extra memory and now you can access up to the size you requested.
If there's not enough 'extra' memory, or if the realloc implementation is simple, then realloc will allocate a new block, copy the data into the new block, free the old block, and return the new pointer.
Reducing the amount of memory for an array will pretty much always mean allocating a new, smaller array, copying the content into the new array, and then freeing the old, larger array. For example vector::shrink_to_fit and the old 'swap with empty' trick do this.
If you want to avoid having too much memory allocated, then you should simply avoid allocating too much in the first place. You should just allocate the correct amount to start with.
One side benefit if this approach is that it means you won't engage in the bad practice of, for example, allocating an array of some fixed size which you think is larger than you will ever need:
#include <iostream>
#include <string>
int main() {
std::string user_input[10000]; // should be enough for anyone
int count = 0;
for (std::string s; std::cin >> s;) {
user_input[count] = s;
++count;
}
magic_array_size_reducing_function(user_input, count);
}
The above code is wrong, because the user might exceed the fixed limit and cause the program to break. In fact, any time you see such fixed limits you should be suspicious, and the code probably needs to be fixed. You should also be suspicious of any beginning programming book or course that asks you to do this.
The right way to write this is to not have fixed limits, and instead dynamically increase resource usage as necessary.
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::string user_input;
for (std::string s; std::cin >> s;) {
user_input.push_back(s);
}
//...
}
Doing this by hand simply means doing the allocation/copy/deallocation dance as necessary. Below is an example where I implement just the bare minimum.
#include <iostream>
#include <string>
struct dynamic_string_array {
int capacity, size;
std::string *user_input;
dynamic_string_array() {
capacity = 0;
size = 0;
user_input = nullptr;
}
~dynamic_string_array() {
delete [] user_input;
}
void push_back(std::string const &s) {
if (size == capacity) {
int new_capacity = capacity ? 16 : capacity * 1.5;
std::string *new_user_input = new std::string[new_capacity];
for (int i = 0; i < size; ++i) {
new_user_input[i] = user_input[i];
}
// ---
delete [] user_input;
user_input = new_user_input;
capacity = new_capacity;
}
user_input[size] = s;
++size;
}
};
int main() {
dynamic_string_array user_input;
for (std::string s; std::cin >> s;) {
user_input.push_back(s);
}
//...
}
#include <cstdlib>
#include <cstring>
#include <string>
using std::string;
string *arr_ptr;
int capacity;
void add() {
int old_capacity = capacity;
capacity <<= 1;
// double the capacity
string *tmp_ptr = new string[capacity];
// apply new space
memmove(tmp_ptr, arr_ptr, sizeof(string) * old_capacity);
// copy
delete[] arr_ptr;
// free the original space
arr_ptr = tmp_ptr;
arr_ptr[capacity - 1] = "occupied";
// without this statement, everything "seems" to be fine.
}
int main() {
arr_ptr = new string[1];
capacity = 1;
for (int i = 0; i < 3; i++) add();
}
Run the code. As you can see, the program crashes when string's desctrutor is invoked. Try to comment the line of delete and check again.
I suspect that std::string keeps some address information of itself. It won't be informed when its location in memory has changed.
Furthermore, since memmove doesn't always work as expected, what's the appropriate expression of copying an array of class instance in C++?
memmove is a lowlevel function for copying bytes. This means that the value of an array of bytes is copied to another array. This is fine for POD data, but not for anything else. The reason is that classes can have a copy constructor, which isn't called by memmove and classes can have extra data like a vpointer for calling virtual member-functions.
The easiest solution for you is to replace memmove with std::copy for (#include <algorithm>) which copies entries instead of bytes:
std::copy(arr_ptr, arr_ptr + old_capacity, tmp_ptr);
I believe what you are looking for is string::reserve.
In your code, you are also trying to make an array of string (and not a string as an array of character).
What you are doing here is copying the object 'string', and not its content (since you are not calling its constructor / destructor).
Therefore, when you 'delete' your "arr_ptr", the destructor free the data associated.
When you try to access it with tmp_ptr, the program segfault.
1st you don't initialize the value of your capacity as in:
int capacity;
should be:
int capacity = 0;
and when you try this operation:
arr_ptr[capacity - 1] = "occupied";
there is a referencing error that may occur.
The behaviour of this program is ::std::string implementation dependent.
If the implementation of string uses heap memory to store the characters, memmoveing an instance of string means there are two pointers pointing to the same heap memory. Calling the destructor of one of the string instance causes the heap memory to be freed, resulting in the other instance of string to have a dangling pointer.
So don't memmove strings :)
I'm in the unfortunate position to write my own vector implementation (no, using a standard implementation isn't possible, very unfortunately). The one which is used by now uses raw bytes buffers and in-place construction and deconstruction of objects, but as a side-effect, I can't look into the actual elements. So I decided to do a variant implementation which uses internally true arrays.
While working on it I noticed that allocating the arrays would cause additional calls of construtor and destructor comapred to the raw buffer version. Is this overhead somehow avoidable without losing the array access? It would be nice to have it as fast as the raw buffer version, so it could be replaced.
I'd appreciate as well if someone knows a good implementation which I could base my own on, or the very least get some ideas from. The work is quite tricky after all. :)
Edit:
Some code to explain it better.
T* data = new T[4]; // Allocation of "num" elements
data[0] = T(1);
data[1] = T(2);
delete[] data;
Now for each element of the array the default constructor has been called, and then 2 assignment methods are called. So instead just 2 constructor calls we have 4 and later 4 destructor calls instead just 2.
as a side-effect, I can't look into the actual elements.
Why not?
void* buffer = ...
T* elements = static_cast<T*>(buffer);
std::cout << elements[0] << std::endl;
Using true arrays means constructors will be called. You'll need to go to raw byte buffers - but it's not too bad. Say you have a buffer:
void *buffer;
Change that to a T *:
T *buffer;
When allocating, treat it as a raw memory buffer:
buffer = (T *) malloc(sizeof(T) * nelems);
And call constructors as necessary:
new(&buffer[x]) T();
Your debugger should be able to look into elements of the buffer as with a true array. When it comes time to free the array, of course, it's your responsibility to free the elements of the array, then pass it to free():
for (int i = 0; i < nInUse; i++)
buffer[x].~T();
free((void*)buffer);
Note that I would not use new char[] and delete[] to allocate this array - I don't know if new char[] will give proper alignment, and in any case you'd need to be careful to cast back to char* before delete[]ing the array.
I find the following implementation quite interesting: C Array vs. C++ Vector
Besides the performance comparison, his vector implementation also includes push/pop operations on the vector.
The code also has an example that shows how to use the macros:
#include "kvec.h"
int main() {
kvec_t(int) array;
kv_init(array);
kv_push(int, array, 10); // append
kv_a(int, array, 20) = 5; // dynamic
kv_A(array, 20) = 4; // static
kv_destroy(array);
return 0;
}
This is a bit unclear to me... So, if I have a function:
char *test(int ran){
char *ret = new char[ran];
// process...
return ret;
}
and then call it multiple times:
for(int i = 0; i < 100000000; i++){
char *str = test(rand()%10000000+10000000);
// process...
// delete[] str; // do i have to delete it here?
}
So the question is, do I have to use delete[] for each new[] call?
You don't have to. But if you don't delete memory you reserved with 'new' you will start running out of memory eventually (memory leak).
Yes you do, otherwise you'll have a memory leak.
It's not the greatest idea to allocate in one function and free in another, though. Why not allocate in the for loop and pass the pointer to test -- this keeps the new and delete together in the code.
The answer was already given, but as you tagged the question as C++, and not as C, this is how you probably want to do it in C++ (of course, there might be other reasons not to, but there is little chance).
vector<char> (int ran){
vector<char> ret(char);
// process...
return ret;
}
And to call it:
for(int i = 0; i < 100000000; i++){
vector<char> str = test(rand()%10000000+10000000);
// process...
}
No new, thus no delete thus no memory leak.
Actually, you also probably want to use std::string instead of char* (I used vector to give a more general example).
Don't worry of data that will be copied. The compiler will optimize it out.
Edit : ok, it might not optimize it out :) however there are big chances it will. And as long there is no performance issues, go for the simplest version.
I have a program in C++ that has a BYTE array that stores some values. I need to find the length of that array i.e. number of bytes in that array. Please help me in this regard.
This is the code:
BYTE *res;
res = (BYTE *)realloc(res, (byte_len(res)+2));
byte_len is a fictitious function that returns the length of the BYTE array and I would like to know how to implement it.
Given your code:
BYTE *res;
res = (BYTE *)realloc(res, (byte_len(res)+2));
res is a pointer to type BYTE. The fact that it points to a contiguous sequence of n BYTES is due to the fact that you did so. The information about the length is not a part of the pointer. In other words, res points to only one BYTE, and if you point it to the right location, where you have access to, you can use it to get BYTE values before or after it.
BYTE data[10];
BYTE *res = data[2];
/* Now you can access res[-2] to res[7] */
So, to answer your question: you definitely know how many BYTEs you allocated when you called malloc() or realloc(), so you should keep track of the number.
Finally, your use of realloc() is wrong, because if realloc() fails, you leak memory. The standard way to use realloc() is to use a temporary:
BYTE *tmp;
tmp = (BYTE *)realloc(res, n*2);
if (tmp == NULL) {
/* realloc failed, res is still valid */
} else {
/* You can't use res now, but tmp is valid. Reassign */
res = tmp;
}
If the array is a fixed size array, such as:
BYTE Data[200];
You can find the length (in elements) with the commonly used macro:
#define ARRAY_LENGTH(array) (sizeof(array)/sizeof((array)[0]))
However, in C++ I prefer to use the following where possible:
template<typename T, size_t N>
inline size_t array_length(T data[N])
{
return N;
};
Because it prevents this from occurring:
// array is now dynamically allocated
BYTE* data = new BYTE[200];
// oops! this is now 4 (or 8 on 64bit)!
size_t length = ARRAY_LENGTH(data);
// this on the other hand becomes a compile error
length = array_length(data);
If the array is not a fixed size array:
In C++, raw pointers (like byte*) are not bounded. If you need the length, which you always do when working with arrays, you have to keep track of the length separately. Classes like std::vector help with this because they store the length of the array along with the data.
In the C way of doing things (which is also relevant to C++) you generally need to keep a record of how long your array is:
BYTE *res;
int len = 100
res = (BYTE *)realloc(res, (byte_len(len)));
len += 2;
res = (BYTE *)realloc(res, (byte_len(len)));
An alternative in the C++ way of doing things s to use the std::vector container class; a vector has the ability to manage the length of the array by itself, and also deals with the issues of memory management..
EDIT: as others have pointed out the use of realloc here is incorrect as it will lead to memory leaks, this just deals with keeping track of the length. You should probably accept one of the other replies as the best answer
Given the information you seem to have available, there is no way to do what you want. When you are working with arrays allocated on the heap, you need to save the size somewhere if you need to work with it again. Neither new nor malloc will do this for you.
Now, if you have the number of items in the array saved somewhere, you can do this to get the total size in characters, which is the unit that realloc works with. The code would look like this:
size_t array_memsize = elems_in_array * sizeof(BYTE);
If you are really working with C++ and not C I would strongly suggest that you use the vector template for this instead of going to malloc and realloc. The vector template is fast and not anywhere near as error prone as rolling your own memory management. In addition, it tracks the size for you.
When you allocate the pointer initially you also need to keep track of the length:
size_t bufSize = 100;
BYTE* buf = malloc(sizeof(BYTE ) * bufSize);
When you re-allocate you should be carefull with the re-alloc:
BYTE* temp = realloc(buf,sizeof(BYTE ) * (bufSize+2));
if (temp != NULL)
{
bufSize += 2;
buf = temp;
}
If it is a local variable allocated on the stack you can calculate it like this:
BYTE array[] = { 10, 20, 30, ... };
size_t lenght = sizeof(array) / sizeof(BYTE);
If you receive a pointer to the beginning of the array or you allocate it dynamically(on the heap), you need to keep the length as well as the pointer.
EDIT: I also advise you use STL vector for such needs because it already implements dynamic array semantics.