tags:

views:

72

answers:

5

Hi,

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

+1  A: 

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.

Steve Townsend
+1  A: 

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 ....

Billy ONeal
Can i know why and what would you recommend to use instead of those?
Sunil
@ Sunil this is the C way of doing things for the correct way to do this in C++ refer here http://www.cplusplus.com/doc/tutorial/files/Also instead of malloc and free use new to allocate and delete to deallocate memory.
anijhaw
@Sunil, anijhaw: Or a std::vector
Merlyn Morgan-Graham
@anijhaw + @Sunil: You should usually be using std::vector in cases where you need a dynamically allocated buffer rather than manually managing memory in C++. In C, that's perfectly fine.
Billy ONeal
Oh, and I really really wish people would leave FREAKING COMMENTs before/just after downvoting answers :(
Billy ONeal
@Billy: Wasn't me. I upvoted :)
Merlyn Morgan-Graham
even I did not downvode. Yes I agree we should be using vectors.
anijhaw
+1  A: 

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
Merlyn Morgan-Graham
Thanks Merlyn Morgan-Graham. Is it possible to use realloc. For example, after doing what I wanted with buffer[1] I would realloc the memory to a smaller size. wouldn't this free the memory chunk by chunk? (Though I have no idea if its possible)
Sunil
I would not recommend realloc for this purpose... first of all, realloc may involve copying whole buffer to a new block of memory, secondly, if you are reallocing to a smaller size, you will loose the end, and keep only the beginning.
Akusete
The size of the memory block pointed to by the ptr parameter is changed to the size bytes, expanding or reducing the amount of memory available in the block. (ref : http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/). So There is a pointer to the memory block and it should increase or decrease the memory size right? What if we make the pointer to point the beginning of the memory block.
Sunil
So, before continuing off onto a wild goose chase here, what are you trying to accomplish by reallocating and freeing buffers while doing this reading? Why do you want to do this? Why is 1024 bytes too big to keep around? You may very well have legit answers to these questions, I just think you should present them before you or we bother.
Merlyn Morgan-Graham
+1  A: 

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)

Chubsdad
+1 for standard reference. (Even if the bold italics are a bit much...)
Billy ONeal
@Billy ONeal: Thanks. Have retained only italics.
Chubsdad
@chubsdad: Much better... +.. oh wait, already did that :)
Billy ONeal
A: 

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]
   }

}
Akusete
I don't see any use of the Standard Template Library in that code.... Also, that code has problems as it is not exception safe. You should replace the explicit calls to `new` and `delete` with `std::vector<char>`.
Billy ONeal
@Billy: std::vector<char> is an alternative worth considering, but to say it "should" be used is excessive. An auto_ptr (or other smart pointer) is another alternative for exception safety.
Tony
Tony, `auto_ptr` cannot be used with arrays (`unique_ptr` would be okay in C++0x). Considering that there is no efficiency penalty for `vector`, and considering it's built into the standard instead of requiring external libraries, I still think **should** is appropriate here.
Billy ONeal
@Billy ONeal: I completely agree with you about using std::vector, I guess I was just trying to write a 'simplified' solution.
Akusete
@Tony: std::vector gives you a heap allocated contiguous block of memory which is scoped and exception safe. The only overhead is if you want to return the vector, it will copy rather than pass by reference, but otherwise its fine.
Akusete