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.
Related
I am trying to convert some C++ code into Delphi. Hopefully you can help.
This is the block of code that needs to be converted;
group = (inum - 1) / inodes_per_group;
index = ((inum - 1) % inodes_per_group) * inode_size;
inode_index = (index % blocksize);
desc[group].bg_block_bitmap;
blknum = desc[group].bg_inode_table + (index / blocksize); //Specifically this line
Now desc is declared as EXT2_GROUP_DESC *desc; which is defined elsewhere;
typedef struct tagEXT2_GROUP_DESC
{
uint32_t bg_block_bitmap; /* points to the blocks bitmap for the group */
uint32_t bg_inode_bitmap; /* points to the inodes bitmap for the group */
uint32_t bg_inode_table; /* points to the inode table first block */
uint16_t bg_free_blocks_count; /* number of free blocks in the group */
uint16_t bg_free_inodes_count; /* number of free inodes in the */
uint16_t bg_used_dirs_count; /* number of inodes allocated to directories */
uint16_t bg_pad; /* padding */
uint32_t bg_reserved[3]; /* reserved */
}__attribute__ ((__packed__)) EXT2_GROUP_DESC;
desc is initalised using calloc as follows;
desc = (EXT2_GROUP_DESC *) calloc(totalGroups, sizeof(EXT2_GROUP_DESC));
First question; In C++, how is it possible to access a pointer to a record as an array like this? Why is there no array type required in C++?
Second question: Below is my Delphi conversion, why can I not access desc as an array without giving it a type?
My way is obviously wrong. What is the correct way to go about it?
Type
PTExt2_Group_Desc = ^TExt2_Group_Desc;
TExt2_Group_Desc = packed Record
bg_block_bitmap : Cardinal;
bg_inode_bitmap : Cardinal;
bg_inode_table : Cardinal;
bg_free_blocks_count : Word;
bg_free_inodes_count : Word;
bg_used_dirs_count : Word;
bg_pad : Word;
bg_reserved : Array[0..2] of Cardinal;
end;
//Calloc function found from Google
function CAlloc(Items, Size: Cardinal): Pointer;
begin
try
GetMem(Result, Items * Size);
FillChar(PByte(Result)^, Items * Size, 0);
except
on EOutOfMemory do
Result := nil;
end;
end;
self.desc := PTExt2_Group_Desc(calloc(totalGroups, sizeof(TEXT2_GROUP_DESC)));
index := ((inum-1) MOD self.inodes_per_group) * self.inode_size;
inode_index := (index MOD self.block_size);
blknum := self.desc[group].bg_inode_table + (index div self.block_size); //Error - Array type required
To answer your question how is it possible (by which I take it you mean "sensible") to use a pointer as an array...
A pointer is simply a reference to an area of memory. A typed pointer ensures that the layout of that memory conforms to a particular specification. An array is merely a sequential arrangement of uniform memory areas, so an array reference applied to a base pointer is logically equivalent to simply taking an offset into the memory. Instead of a byte offset, you are indicating an offset as a multiple (the array index) of a number of bytes, being the number of bytes occupied by the type referenced by pointer.
e.g. if you have a pointer P referencing memory that is a notional array of 16-bit words (2 bytes) then:
P[4] = P + (4 * 2) = P + 8 bytes
i.e P[4] = the 16-bit word located at P + 8
Now to the Delphi technique(s) involved:
If you are using Delphi 2009 or later, you can enable this syntax by enabling pointer arithmetic:
{$POINTERMATH ON}
If you are using an earlier version of Delphi, or prefer not to enable pointer arithmetic for some reason, you can achieve the same result by introducing an array type declaration:
TExt2_Group_Desc = packed record
..
end;
TExt2_Group_DescArray = array [0..255] of TExt2_Group_Desc;
PTExt2_Group_Desc = ^TExt2_Group_DescArray;
Doing this means that your pointer type must always be used as a reference to an array however, so you may prefer to create this array-form declaration as a separate type:
PTExt2_Group_Desc = ^TExt2_Group_Desc;
TExt2_Group_Desc = packed record
..
end;
TExt2_Group_DescArray = array [0..255] of TExt2_Group_Desc;
PTExt2_Group_DescAsArray = ^TExt2_Group_DescArray;
The bounds on the array are not strictly important (in terms of memory use) since you are not declaring a variable of that type, only using it as a way of coercing the array-form pointer type. However, if you have bounds checking enabled then you should ensure that the bounds on this array declaration are sufficient to accommodate your required indexing range.
The POINTERMATH directive approach is not affected by this since there are no explicit bounds involved in that case.
First question; In C++, how is it possible to access a pointer to a
record as an array like this? Why is there no array type required in
C++?
To answer your first question, C++ has no notion of Variable Length Arrays (VLA). Some C++ compilers offer this as an extension, but the ANSI C++ language specification outlaws them.
So the code you're seeing is one of many ways of compensating for the lack of VLA's. Since arrays store data in contiguous blocks, all that needs to be done is declare a pointer, create the block dynamically (in the case above, using calloc), thus a pointer is returned that denotes the start of the array block.
Once the pointer points to this memory block, the array syntax of using [ ] can be used to access each element.
Note that the code you posted is mostly C in style. There is very little reason (unless you're writing an allocator class) to use calloc in a C++ program. In C++, you would usually use new[] to allocate memory for an array, or use a class such as std::vector to handle the memory management automatically.
Having said this, C99 has VLA's, so the code above need not be done with this version of C. For C++, there are no VLA's that are standard, so the code in your question would be used (albeit, very rarely).
As to your second question concerning Delphi, I guess the answer to the first question can be used as a guide. I am not a Delphi programmer, but what you should investigate is whether Delphi has some sort of dynamic array class or type. That would be the equivalent of the calloc call in C++.
I have an array allocated with malloc:
char *aStr1 = (char* ) malloc (10);
And then I filled this memory:
strcpy(aStr1, "ABCDEFGHI");
After that I created a new pointer aStr2:
char *aStr2 = aStr1 + 5;
And i set fourth element of memory to '\0':
*(aStr1 + 4) = '\0';
And finally, using these two pointers in a simple function:
int checkMem(char *aStr1, char *aStr2);
This function returns true (some none zero value) if aStr1 and aStr2 pointed to one memory block, and returns zero in another case.
How i can implement this function? (I read many linux mans about allocs function and haven't found any information about such problem).
//Added
I need this to do something like that:
char *aStr1 = (char *) malloc (10);
char *aStr2 = aStr1 + 5;
strcpy(aStr1, "ABCDEFGHI");
*(aStr1 + 4) = '\0';
and than:
my_strcat(aStr1, aStr2);
I do not ask for help to implement my_strcat, but maybe, get some hint how i can resolve its problem
//Updated
thanx, for all. I solved it.
Without any low level functions you cannot correctly know, how many memory allocate (maybe on some platform or realization you can do this:
size_t ptr_size = *((size_t *)ptr - 1);
but maybe not for all it will be correct).
And solving is simple: i create local copy of aSrc2, then realloc aSrc1 and copy aSrc2 to new aSrc1.
Unfortunately you cannot tell if two pointers point to memory that belonged to the same initial allocation.
You can create classes/structures that, for instance, save the initial allocation and then you could compare them.
But without added information, you simply cannot tell.
There is no provided standard mechanism for doing this, its up to you to track the memory you received and how big those allocations are, so you'd probably want to provide your own malloc wrapper that tracks what's allocd. Store the pointers in a map so you can use lower_bound to find the nearest allocate to the first string and then check if the second string is in the same allocation.
I have a C++ code...
// global
DWORD* P;
DWORD (*S)[256];
// then later allocate memory
P = new DWORD[18];
S = new DWORD[4][256];
// later on, free memory
delete P;
delete [] S;
that I want to convert to C. I tried ..
/* global */
DWORD* P;
DWORD (*S)[256];
/* allocate */
P = malloc(sizeof(DWORD[18]));
S = malloc(sizeof(DWORD[4][256]));
/* free */
free(P);
free(S);
It works and I don't get any errors or warnings from the compiler (GCC) but I'm not sure if this is the right way, and I'm guessing it leaks memory, probably in freeing the multidimensional array.
Also, are those arrays too big to allocate on the stack? Can I do it like this instead and forget about malloc/free?
DWORD P[18] = {0};
DWORD S[4][256] = {{0}};
That code is perfectly safe. malloc() and free() are only concerned with allocating a number of bytes from the heap. This is why you use sizeof() inside the call to malloc(), to determine the number of bytes that datatype needs. You could also, for example, do S = malloc(sizeof(DWORD) * 4 * 256) and get the same result.
To answer the second half of your question, neither of those arrays are even close to being too big for the stack. You could stack-allocate those in either C or C++.
I am new to programming and I am trying to understand the difference between
A = (char * ) malloc(sizeof(char)*n);
and
A = (char * ) malloc(sizeof(char));
or
A = new char [n];
and
A = new char;
What is the default memory that a compiler is allocating to this pointer, when I do not specify the number of objects of particular data type.
Also when I declare
A = new char [n];
cout << A[n+1];
it does not give me a segmentation fault.
Should It not give segmentation fault because I am trying to access memory beyond what has been allocated for the Array.
Memory is not "allocated to this pointer", it's allocated and then you get a pointer to the memory.
This:
char *a = malloc(sizeof(char) * n);
is the same as
char *a = malloc(n);
since sizeof(char) is always 1. They both allocate space for n characters worth of data, and return a pointer to the location where the first character can be accessed (or NULL on failure).
Also, the casts are not needed in C, you should not have any.
Since sizeof(char) is 1, the second call is equivalent to:
char *a = malloc(1);
which means it allocates a memory block of size 1. This is of course distinct from the pointer to that memory block (the value that gets stored in the pointer variable a). The pointer is most likely larger than 1 char, but that doesn't affect the size of the block.
The argument to malloc() specifies how many chars to allocate space for.
I ignored the new usage, since that is C++ and the question is tagged C.
A = (char * ) malloc(sizeof(char)*n);
This allocates space for n characters.
A = (char * ) malloc(sizeof(char));
This allocates memory for 1 character.
Every call to malloc allocates memory in the heap.
The other code is C++, and it's exactly the same, except that it will use stack memory if A is a local variable. Accessing A[n+1] may or may not yield a segfault. A[n+1] can reference a memory address that you are allowed to use. Segfault happens when you go out of the region of memory you can access, and the way it works is that there is a "red zone" from which it is considered you accessed invalid memory. It may be the case that A[n+1] just isn't "invalid enough" to trigger a segfault.
allocate space for N characters (N should be some positive integer value here)
char *ma = (char * ) malloc(N);
char *na = new char [N];
don't forget to release this memory ...
delete [] na;
free(ma);
allocate space for a single character
char *mc = (char * ) malloc(sizeof(char));
char *nc = new char;
Now, as the others have pointed out, you tagged this C, but half your code is C++. If you were writing C, you couldn't use new/delete, and wouldn't need to cast the result of malloc.
Oh, and the reason you don't get a segmentation fault when you read off the end of your array is that this is undefined behaviour. It certainly could cause a SEGV, but it isn't required to check, so may appear to work, at least some of the time, or fail in a completely different way.
Well, the compiler doesn't allocate memory for the data. Only the pointer which is either 4 or 8 bytes depending on your architecture.
There is no difference between the first two and the last two in terms on functionality. Most C++ libraries I've seen use malloc internally for new.
When you run the code to allocate n characters and you print out the n + 1th character, you aren't getting a segmentation fault most likely because n isn't a multiple of some number, usually 8 or 16. Here's some code on how it might do that:
void* malloc(size_t size) {
if (size & 0x7 != size)
size = size & 0x7 + 1;
return _malloc(size);
}
So, if you requested, say, 5 bytes, malloc would actually allocate, with that code, 8 bytes. So, if you request the 6th byte (n + 1), you would get garbage, but it is still valid memory that your program can access.
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]
}
}