I have a problem with sizeof(). I have a pointer in a class that I have created before. And this pointer is initialized as
static Book* books;
so it does point nothing. I want to determine if the pointer does point any array or not. So first question is that what are the solutions to do that because I can change the address of this pointer during the runtime to point an array. I try to use sizeof(pointer) but it does not help me enough. The return is the number 4. I can evaluate in this way if it refers anything or not.
This is my class :
class Tool
{
private:
static Book* books;
public:
static char* pgetStringIntoArray(string);
static string* pgetStringFromArray(char*);
static void printCharArray(char*);
static bool* addBook(Book*);
static bool* isStored(Book*);
};
And this is the method having a problem :
bool* Tool::isStored(Book* book)
{
bool* stored = new bool(false);
if(Tool::books)
{
cout << "NULL" << endl;
} else {
return stored;
}
}
No, you can't use sizeof to determine if the pointer is pointing to something. sizeof a pointer will be always the same size in the same architecture.
You can do this:
Tool::Book* books = NULL;
And, if you want to check if it's pointing to a valid non-null value, just do:
if (Tool::books) {
// books is pointing to something
}
Whenever you allocate memory for your pointer (array), if the allocation succeeds, the pointer will no longer be null. Since you are using C++, consider using std::vector to hold arrays of dynamic dimensions instead of arrays (pointers).
Much like C, C++ is statically typed - the various type sizes as returned by the sizeof operator are determined at compile time and do not change.
The proper way to do what you are asking would be to initialize your pointer to NULL and check for that afterwards. NULL is guaranteed not to refer to any valid memory address, which makes it a good marker for a non-existent pointer target. Initializing your pointers is a good practice anyway - it saves you from potential issues from dereferencing uninitialized pointers, issues that at best will result in nasty memory errors.
And yes, explicitly initializing the rest of your variables is also a good idea...
EDIT:
One not-so-minor detail: static fields in C and C++ programs are stored in a special section (e.g. BSS) of the executable and are automatically initialized to zero as the program loads. Therefore, you do not need to explicitly initialize static pointers to NULL; that has already been done for you...
Your problem is more with understanding pointers than with sizeof.
sizeof is a compile-time operation. For a pointer it always return sizeof(void*) (which is 8 bytes on most 64 bits architectures). Except for VLAs, sizeof returns a compile time constant.
C don't know the used size of any pointed zone -think of the result of malloc as an example- (because you could do pointer arithmetic). You need to manage it by yourself if needed.
Related
As the title suggests, is it possible to start an array when you have the address given. i.e. If my start address is 10002432,basically &array[0] = 10002432 and array[1] will be stored in the next sequential address. I am able to copy to the said address using Pointers but instead of pointers, I would like to use arrays which are dynamically allocated. My current code is as follows which is using Pointers. I have tried various solutions that are currently are online but none of them are able to provide a definite solution.
I was thinking to make an overloaded new operator, but i get stuck on it as well, since underlying the overloaded new operator we use malloc which also doesnot allow to specify the start address.
I am running this code in a simulator (gem5), where I have control over memory addresses as I can specify how the virtual addresses map on the physical addresses.
int main(int argc, char const *argv[])
{
uintptr_t address = 10002432;
int *Pointer = (int*) address;
int *Pointer2 = Pointer;
for (int i = 0; i < 32; ++i)
{
*Pointer = i;
Pointer = Pointer + 4;
}
for (int i = 0; i < 32; ++i)
{
printf("%d\n",Pointer2 );
Pointer2 = Pointer2 + 4;
}
}
Any assistance would be highly appreciated.
No, it is not possible to "allocate" memory from specific address in standard C++.
Within an operating system that uses virtual memory (i.e. all modern multi-tasking operating systems), there is typically no system specific way to do such allocation either. It is however common to use constant addresses documented by the system provider on embedded systems. You can typically consider such memory "always allocated". Perhaps this applies to your simulator.
You can create dynamic objects into uninitialised memory through a pointer. The syntax for doing this is called placement new. Ths is sometimes useful to reuse "generic" allocated memory for some in-place containers such as std::vector, as well as in the mentioned case where the address is constant.
Important note: The address is assumed to satisfy the alignment requirement of the created object. If it is not satisfied, then the behaviour of the program is undefined.
Although there is syntax for doing so, it is not possible to create an array this way in practice. Array placement new is not guaranteed to start the array from the provided address. Some implementation specific amount of memory at the beginning from the address may be used by the language implementation.
Instead of creating an array, you can simply create the elements individually, separately, and pretend that they are in an array. This is what the implementation of std::vector in your standard library probably does as well. There are helper functions for that in the standard library:
using T = int;
std::uintptr_t address = 10002432; // Note: using hex would be more conventional
const std::size_t size = 32;
T* p = std::launder(reinterpret_cast<T*>(address));
if (!std::align(alignof(T), sizeof(T), p, sizeof(T)))
throw std::invalid_argument("bad alignment");
std::uninitialized_fill_n(p, size, T{});
// use it
std::destroy_n(p, size);
// Instead of filling from the value initialised value,
// you can copy a range. Here is an example with C++20 ranges:
auto i = std::views::iota(T{});
std::uninitialized_copy_n(i.begin(), size, p);
// use it
std::destroy_n(p, size);
Note that the destruction part is unnecessary in case of int and other trivial types, but mandatory for non-trivially-destructible types. This is a trivial example, and is not exception safe. If exception is thrown after successful initialisation, the destruction won't be called. You can use a RAII idiom to make sure the destruction happens.
If the given pointer is derived from a valid pointer to previously existing objects such as when reusing memory of a trivial object (which is not the case in the example), then std::launder is necessary as used in the example. It may be unnecessary otherwise (which is the case in the example, so you may get rid of laundering if you know what you're doing; but keeping it doesn't hurt).
When reinterpreting integer as pointer, the language standard provides no guarantee what memory address the value will be mapped to. You have to rely on guarantees provided by the language implementation for that memory address to be in any way useful. Except in the case you converted from a valid pointer into an integer (of sufficient size), and back to same pointer type, then that is guaranteed to be the same pointer value. But this case does not apply in the example.
Given a function foo with a statement in it:
void foo() {
std::string * s;
}
Is memory reclaimed after this function returns?
I am assuming yes because this pointer isn't pointing to anything but some people are saying no - that it is a dangling pointer.
std::string* s is just an uninitialized pointer to a string. The pointer will be destroyed when function foo returns (because the pointer itself is a local variable allocated on the stack). No std::string was ever created, hence you won't have any memory leak.
If you say
void foo() {
std::string * s = new std::string;
}
Then you will have memory leak
This code is typical when people learn about strings a-la C, and then start using C++ through C idioms.
C++ classes (in particular standard library classes) treat objects as values, and manage themselves the memory they need.
std::string, in this sense is not different from an int. If you need a "text container", just declare an std::string (not std::string*) and initialize it accordingly (uninitialized std::strings are empty by definition - and default constructor) than use it to form expression using method, operators and related functions like you will do with other simple types.
std::string* itself is a symptom of a bad designed environment.
Explicit dynamic memory in C++ is typically used in two situation:
You don't know at compile time the size of an object (typical with unknown size arrays, like C strings are)
You don't know at compile time the runtime-type of an object (since its class will be decided on execution, based on some other input)
Now, std:string manage itself the first point, and does not support the second (it has no virtual methods), so allocating it dynamically adds no value: it just adds all the complication to manage yourself the memory to contain the string object that is itself a manager of other memory to contain its actual text.
This code just creates a pointer to somewhere in memory, which contains string value and it points to somewhere which has been allocated before and it does not allocate new string.
it just allocate a memory for pointer value and after function return it's no more valid...
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Declaring a pointer to struct in C++ automatically allocates memory for its members. Am I wrong?
Say if I define the structure Human as:
struct Human{int year, Human* Mom};
does the expression
Human* Bob;
automatically allocate a memory for both Bob and the Human object it is pointing to?
Because I noticed that
Bob == NULL
is false;
Does this mean that the above expression creates a static memory of the object Human?
Also, I noticed that
Bob->year
is NOT initialized to 0 automatically, but
Bob->Mom
is being initialized to NULL, why is that?
Another thing, if I allocate the memory dynamically, e.g.
Human* Bob = new Human;
Then I found that
Bob->Mom
is no longer NULL, how this is happening?
At minimum, the structure declaration should be corrected to:
struct Human { int year; Human *Mom; };
The statement:
Human *Bob;
then creates a storage location, but does not initialize it if it is created inside a function. If it is at global scope, it would be initialized to zero (NULL), but you say Bob == NULL is false, so it must be an uninitialized local variable. It doesn't point at anything. Any use of it other than as the target for an assignment invokes undefined behaviour because the value in Bob is undefined.
No; the definition shown does not allocate storage for Bob to point at.
Your other observations all depend on the quirks of your runtime system. Because the behaviour is undefined, anything can happen and it is 'OK' according to the standard. You need a default constructor for the type to get the values set sensibly when you use:
Human *Bob = new Human;
You have not provided one, and the system doesn't need to provide one, so the object pointed at is uninitialized.
No, it doesn't allocate memory. Bob is a pointer with garbage value, so who knows what it's pointing to.
does the expression Human* Bob; automatically allocate a memory for both Bob and the Human object it is pointing to? Because I noticed that Bob==NULL is false; Does this mean that the above expression creates a static memory of the object Human?
No, it doesn't. Bob is not initialised, so will just point to some random garbage. You must explicitly allocate memory for Bob.
Another thing, if I allocate the memory dynamically, e.g. Human* Bob=new Human; Then I found that Bob->Mom is no longer NULL, how this is happening?
As above, uninitialised memory could have anything in it. Trying to follow the pointer will lead to disaster. Good practice is to initialise all pointers to NULL or to immediately point them at an allocated block of memory.
In your code, the only instruction you have given to the compiler is to create a pointer (either a 32 bit or 64 bit variable) which you intend to point to a structure of type "Human".
Since you have not initialized the pointer, its value is most likely what was in that memory space - that could be a 0 (NULL), or anything else.
When you call Bob->Mom, you are dereferencing the pointer (Bob) and looking at an area in memory that is arbitrary (potentially a space you are not allowed access to). You most likely will get a segmentation fault (on a *nix machine).
What you should do is:
Human* Bob = new Human();
That will create dedicated space for the structure and return the address of that structure and assign it to the pointer Bob. Now, when you dereference Bob, it will actually point to a space which has been allocated specifically for the Human structure.
Its your responsibility to initialize pointer values. Unless you have set them to something (like 0 or NULL), their value is undefined and you may get a different uninitialized pointer value with each corresponding allocation.
In terms of allocation, you have defined a recursive or self-referential data structure. Consider what happens if it in fact did allocate memory for an additional Human for the Mom member; it would then have to allocate another Human for Bob->Mom->Mom and so on...
So, no. Only one Human is allocated. Any native pointer is just a memory address location, nothing more.
You can make pointer initialization easier on yourself if you use a constructor:
struct Human {
int year;
Human *Mom;
Human() : year(0), Mom(NULL) {}
};
Related to a recent question, I wrote the following code:
int main()
{
char* x = new char[33];
int* sz = (int*)x;
sz--;
sz--;
sz--;
sz--;
int szn = *sz; //szn is 33 :)
}
I do know it's not safe and would never use it, but it brings to mind a question:
Is the following safe? Is it a memory leak?
char* allocate()
{
return new char[20];
}
int main()
{
char* x = allocate();
delete[] x;
}
If it's safe, doesn't that mean we can actually find the size of the array? Granted, not in a standard way, but is the compiler required to store information about the size of the array?
I am not using or plan on using this code. I know it is undefined behavior. I know it isn't guaranteed by anything. It's just a theoretical question!
Is the following safe?
Yes, of course that's safe. First snippet has UB however.
If it's safe, doesn't that mean we can actually find the size of the array? Granted, not in a standard way, but is the compiler required to store information about the size of the array?
Yes, generally extra data is stored before the first element. This is used to call the correct number of destructors. It's UB to access this.
required to store information about the size of the array?
No. It only requires delete[] work as expected. new int[10] could simply be a plain malloc call, which would not necessarily store the requested size 10.
This is safe, and is not a memory leak. The standards require that delete[] handle the freeing of memory by any array allocation.
If it's safe, doesn't that mean we can actually find the size of the array?
The standards don't put specific requirements on where and how the allocated size is stored. This could be discoverable as shown above, but different compilers/platforms could also use a completely different methodology. As such, it's not safe to rely on this technique to discover the size.
I know that in c, the size of any malloc on the heap resides before the pointer. The code for free relies on this. This is documented in K&R.
But you should not rely on this always being there or always being in the same position.
If you want to know the array length then I would suggest you create a class or struct to record capcity along side the actual array, and pass that around your program where you would previously just pass a char*.
int main()
{
char* x = new char[33];
int* sz = (int*)x;
sz--;
sz--;
sz--;
sz--;
int szn = *sz; //szn is 33 :)
}
This is an undefined behavior, because you access the memory location that you didn't allocate.
is the compiler required to store information about the size of the array?
No.
If it's safe, doesn't that mean we can actually find the size of the array?
You do not do anything special in the 2nd code snipet, therefore it's safe. But there are no ways to get the size of the array.
I am not sure it the delete must know the size of the array when the array is allocated with basic types (that doesn't demand a call to the destructor). In visual studio compilers, the value is stored only for user defined objects (in this case, delete[] must know the size of the array, as it must call their destructors).
Where in the memory the size is allocated is undefined (in visual studio it is in the same place of the gcc).
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.14
There are two ways to destroy an array, depending on how it was created. In both cases the compiler is required to call a destructor for each element of the array, so the number of elements in the array must be known.
If the array is an automatic variable on the stack, the number of elements is known at compile time. The compiler can hard-code the number of elements in the code it emits for destroying the array.
If the array is dynamically allocated on the heap, there must be another mechanism for knowing the element count. That mechanism is not specified by the standard, nor is it exposed in any other fashion. I think that putting the count at an offset from the front of the array is a common implementation, but it's certainly not the only way, and the actual offset is just a private implementation detail.
Since the compiler must know how many elements are in the array, you'd think it would be possible for the standard to mandate a way of making that count available to programs. Unfortunately this is not possible because the count is only known at destruction time. Imagine that the standard included a function count_of that could access that hidden information:
MyClass array1[33];
MyClass * array2 = new MyClass[33];
cout << count_of(array1) << count_of(array2); // outputs 33 33
Foo(array1);
Foo(array2);
MyClass * not_array = new MyClass;
Foo(not_array);
void Foo(MyClass * ptr)
{
for (int i = 0; i < count_of(ptr); ++i) // how can count_of work here?
...
}
Since the pointer passed to Foo has lost all its context, there's no consistent way for the compiler to know how many elements are in the array, or even if it's an array at all.
I'm reading some code in the Ogre3D implementation and I can't understand what a void * type variable means. What does a pointer to void mean in C++?
A pointer to void, void* can point to any object:
int a = 5;
void *p = &a;
double b = 3.14;
p = &b;
You can't dereference, increment or decrement that pointer, because you don't know what type you point to. The idea is that void* can be used for functions like memcpy that just copy memory blocks around, and don't care about the type that they copy.
It's just a generic pointer, used to pass data when you don't know the type. You have to cast it to the correct type in order to use it.
It's a raw pointer to a spot in memory. It doesn't allow any pointer arithmetic like char * or int *.
Here's some examples of usage
http://theory.uwinnipeg.ca/programming/node87.html
It's a pointer to anything -- just a chunk of memory that you can play with -- might be an object, might be a char. You have to cast to do anything useful with it.
Building off my prior posting...
ATTENTION: All memory addresses here are fictional. I'm just making them up to illustrate a point.
Given:
int data[] = {10,11,12};
We now have:
0xffff0000-0xffff0003 with a value of (int)(10)
0xffff0004-0xffff0007 with a value of (int)(11)
0xffff0008-0xffff000b with a value of (int)(12)
(I'm not going to get into big-endian vs little-endian byte ordering here.)
If we have:
int * p = data;
We now have another memory location somewhere else, say:
0xaaaa0000-0xaaaa0003 with a value of (int*)0xffff0000
We can use p[1] [or *(p + 1)] to refer to *(int*)(0xffff0004) [=11] as sizeof(int)=4 and 0xffff0000+sizeof(int) = 0xffff0004.
If we have:
void * v = data;
We now have another memory location somewhere else, say:
0xbbbb0000-0xbbbb0003 with a value of (void*)0xffff0000.
However, void doesn't have any associated sizeof() information. We can't increment or decrement the pointer. We can't dereference to access the data stored in 0xffff0000. We can only utilize the value as a raw memory address.
If we want to use the data stored in (void*)0xffff0000, we first need to cast it to an appropriate type.
That said, (void *) is still quite useful as a means of passing addresses to arbitrary data structures around. For instance, memset(). It doesn't matter whether I'm zero'ing out a struct tm or a struct sockaddr. We just need a pointer to the struct and its size.
(This should go without saying, but... Beware using memset to zero out a class instance and, in doing so, overwriting the virtual pointer table.)
A void pointer cannot point to a class member in C++.