The following code will cause core dump when deletion. But if comment out "memset", it is good to run.
So, it looks like memset does something wrong. What is the problem of the following code?
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n= 5;
int **p = new int* [n];
for (int i=0; i<n; i++) {
p[i] = new int [n];
}
// if comment out this line, it is good to run.
memset(&p[0][0], 0, n*n*sizeof(int));
// core dump here
for (int i=0; i<n; i++) {
delete [] p[i];
}
delete [] p;
return 0;
}
Allocated memories in p[i]s are not necessarily contiguous. So calling memset to clear the whole of the allocated memory in p[i]s will touch a part of memory which is not for you (the main reason for the segmentation fault). If you want to set them all to zero, you have to iterate through them:
for (int i=0; i<n; i++) {
memset(p[i], 0, n*sizeof(int));
}
What you had created is array of pointers to non-contiguous areas of memory
int **p = new int* [n];
for (int i=0; i<n; i++) {
p[i] = new int [n];
}
Here p[0] points at first area, p[1] at second, p[n] at last. They aren't same object, so from point of view for language lawyer such memset call is Undefined Behavior.
memset(&p[0][0], 0, n*n*sizeof(int)); // Out of bound
&p[0][0] points at first element of array object of n elements ( size n*sizeof(int)). Anything odd allowed to happen after you broke the rules, the broken delete[] call is a typical reaction to such "memory corruption".
Note, you don't need memset for zero-initialization with arrays in C++, all you need is initialize them on creation:
int **p = new int* [n];
for (int i=0; i<n; i++) {
p[i] = new int [n]();
}
IF you want your array to be a continuous two-dimensional array, where every sub-array is adjacent to next one (none of standard tools offer such), you may use the placement new approach.
int **p = new int* [n];
int *pool = new int [n*n]; // the whole array will be here
for (int i=0; i<n; i++) {
p[i] = new (pool + i*n) int [n]();
// Creating subobject arrays using placement parameter
// In this case parameter is a pointer to memory storage
// where new expression would create an object.
// No memory allocation is happening here.
}
....
delete [] p; // deleting array of pointers
delete [] pool; // deleting memory pool
Or even better, avoid naked pointers if possible or exposure of user to such code. Use encapsulation, either standard library types or your own types to hide that "code gore". The problem with such exposed code is that there is no procedure which would deallocate memory if something will interrupt execution, e.g. an exception.
memset
Converts the value ch to unsigned char and copies it into each of the first count characters of the object pointed to by dest. If the object is a potentially-overlapping subobject or is not TriviallyCopyable (e.g., scalar, C-compatible struct, or an array of trivially copyable type), the behavior is undefined. If count is greater than the size of the object pointed to by dest, the behavior is undefined.
Every time new is called, a new block of memory is returned. It does not have to be exactly behind the previous block.
So the memory does not have to be continious, as is required by memset, and memset is writting in memory not assigned to the program, so a crash occurs.
To correctly zero initialize memory, add paranthesis after new:
int **p = new int* [n] (); // With C++11 and later can also be {}
for (int i=0; i<n; i++)
{
p[i] = new int [n] (); // With C++11 and later can also be {}
}
Related
I have passed pointer to a pointer as a parameter to function and the goal is to make an array inside of that function. I have done that step properly and also inside of the function checked the *address and value of the array(local) as well as pointed by the pointer(op_ptr_array_) and they are the same(as desired).
But the problem is occurring while I want to dereference the provided pointer(op_ptr_array). The values are wrong while addresses are matched with the pointed array(local).
My idea is that as the address of op_ptr_array(pointer passed to the function) is equal to the local and op_ptr_array_ (array and pointer inside of the function) so using a for loop *(op_ptr_array+i) will provide me the result where i < op_size.
The approach I have taken is as follows:
#include <iostream>
void op_calculation(unsigned int* ip_ptr_array_,
unsigned int ip_size_,
unsigned int** op_ptr_array_,
unsigned int* op_size_)
{
*(op_size_) = ip_size_ + 2;
std::cout<<"op_size_ address: "<<op_size_<<std::endl;
std::cout<<"op_size_ value: "<<*(op_size_)<<std::endl;
unsigned int local[*(op_size_)];
std::cout<<"making local array to be pointed by op_ptr_array_\n";
for (unsigned int i = 0; i< *(op_size_); i++)
{
local[i]=i+1*3;
std::cout<<local[i]<<" ";
}
std::cout<<"\n";
*op_ptr_array_ = &local[0];
local[3] = 87; // for checking pointer charecter
for (unsigned int i = 0; i < *(op_size_); i++)
std::cout<<"array address: "<<&local[i]<<" ,op_ptr_array address: "<<(*op_ptr_array_)+i<<" ,val of array: "<<local[i]<<" ,val at op_ptr_array: "<<*((*op_ptr_array_)+i)<<std::endl;
// here value and addresses are same which is desired
}
int main()
{
unsigned int ip_size = 10;
unsigned int* ip_ptr_array = new unsigned int[ip_size];
unsigned int op_size;
unsigned int* op_ptr_array;
for(unsigned int i = 0; i < ip_size; i++)
{
ip_ptr_array[i] = i+2*2;
}
op_calculation(ip_ptr_array,
ip_size,
&op_ptr_array,
&op_size);
std::cout<<"Value printing after operation of op_calculation function\n";
std::cout<<"op_size: "<<op_size<<std::endl;
std::cout<<"op_ptr_array\n";
for(unsigned int i = 0; i < op_size; i++)
std::cout<<"Address: "<<(op_ptr_array+i)<<" , Value: "<<*(op_ptr_array+i)<<"\n";
/* Here only addresses are same with `local array` and
address pointed by op_ptr_array_ pointer` which you will find in op_calculation
function but values are different*/
std::cout<<"\n";
return 0;
}
Any idea where I am making the mess is highly appreciable.
Variable local is being declared as a local variable (i.e. on the stack). This falls out of scope when the function op_calculation exits, which means that the memory originally used to allocate local may be used for something else.
This can be corrected by converting local to a pointer and using new to allocate memory for the array’s contents or by declaring local as static, which will place the contents elsewhere in RAM. Keep in mind, if you use static any future calls to op_calculation will overwrite the contents of the array, even if it is still in use elsewhere. This would not be a problem if you used new, but if you use new you will need to remember to deallocate the array using delete[] when it is no longer needed.
I have a piece of code that deals with C++ array.
using namespace std;
#include <iostream>
int main(){
int *p;
p = new int[3];
for(int i = 0; i < 3; i++){
p[i] = i;
}
//delete[] p;
for(int i = 0;i <3; i++){
std::cout << *(p+i) << std::endl;
}
}
How does this code work? How does the memory location *(p+i) work? How is it different from using p[i]. What are the differences on the code if we uncomment the line delete[] p.
1) When you do this:
p = new int[3];
Now, p points to the first element of the dynamically allocated array.
When you do, *(p + i) will lead to simple pointer arithmetic. It will boil down to: value of (<address pointed by p> + <size of type pointed by p> * i) which is equivalent to doing p[i].
That's why it works.
2) In C++, unlike java, you have to explicitly clear the dynamically allocated memory using delete, as there is no GC in C++ (and will never be, as per Bjarne Stroustrup). Otherwise, the memory area will remain acquired for the application lifetime, thereby causing memory leak.
Suggestion:
Place your delete at the end of the program. Otherwise, the loop below it may give SIGSEGV.
Also, Avoid using new and delete as much as you can.
I am learning classes in c++ so I try different things to get used to the classes. Here I am trying to pass a pointer to a class function:
class Pointerss{
int size;
public:
Pointerss(int);
void f();
int *a;
};
Pointerss::Pointerss(int siz){
size = siz;
}
void Pointerss::f(){
cout<<"Size is:"<<size<<"\n";
for (int i=0; i<size; ++i) {
cout<<"a is:"<<a[i]<<"\n";
}
}
int main() {
int size = 5;
Pointerss dd (size);
Pointerss * p = new Pointerss(size);
p[0]=1; p[1]=2; p[2]=3; p[3]=4; p[4]=5;
p->a;
dd.f();
return 0;
}
So the "size" is initialized by a constructor and when "f()" is called the correct digit is printed. But when I assign "p" to "a" ("p->a") and then call "f()" some random numbers are printed. My computer prints :
Size is:5
a is:0
a is:0
a is:1
a is:0
a is:1606416856
Program ended with exit code: 0
what is the difference between "a" and "size" and what should I do to pass a pointer to a function?
Random numbers are printed because Pointerss::f dereferences dd.a which you never initialized. Dereferencing an uninitialized pointer results in undefined behaviour.
That's not the only bug you have. You also allocate memory for a single Pointerss object, which is pointed by p, but then proceed to construct objects in p[1..4] which point to unallocated memory. That also results in undefined behaviour.
Thirdly, you never deallocate the memory that you allocated with new.
Step 1 would be to understand pointers. When you make a int* you only reserve memory to store the pointer itself. You don't reserve memory for any int. So when you try to print the integers you just get random numbers (or perhaps a program crash).
So your class can't hold any integers. You need to change it so that you reserve memory in the constructor and release it in the destructor.
class Pointerss{
int size;
public:
Pointerss(int);
~Pointerss();
void f();
int *a;
};
Pointerss::Pointerss(int siz){
size = siz;
a = new int[size]; // Reserve memory for size integers
// Do some initialization if needed, e.g.
for (int i=0; i < size; i++) a[i] = i;
}
Pointerss::~Pointerss(){
delete[] a; // Release the memory again
}
void Pointerss::f(){
cout<<"Size is:"<<size<<"\n";
for (int i=0; i<size; ++i) {
cout<<"a is:"<<a[i]<<"\n";
}
}
Further you can't make a single pointer to an instance of the class, i.e.
Pointerss * p = new Pointerss(size);
and then use it like
p[0]=1; p[1]=2; p[2]=3; p[3]=4; p[4]=5;
because that is operating on 5 different instances.
Finally the code:
p->a;
does nothing!
You could do
p->a[0] = 5;
but it is unclear what you are trying to do.
Notice that dd and p are refering to two different instances of your class so changing something inside *p doesn't change dd at all.
If you had done:
Pointerss *p = ⅆ
then *p and dd would be the same instance.
I am trying to make a new array in my project
the code is:
#include <iostream>
using namespace std;
void makeArray( int *& arrayPtr, int size );
int main( )
{
int * arrPtr;
int size =10;
makeArray( arrPtr, size );
for(int j=0;j<size;j++)
{
cout<<arrPtr[j]<<endl;
}
}
void makeArray( int *& arrayPtr, int size )
{
int arr[size-1];
for(int i=0;i<size;i++)
{
arr[i]=0;
}
*&arrayPtr=*&arr;
}
According to the requirements i need to use the above "makeArray" method inorder to make the array.
When i run the code the output is garbage values not zero.....
any help will be appreciated
thank you
The way you are creating the array is on the stack, which means that it will not exist after the makeArray function finishes.
You will need to allocate the array on the heap.
So:
int arr[size-1];
should be:
int *arr = new int[size-1];
Also, I think you mean to do this in makeArray():
arrayPtr = arr;
Instead of:
*&arrayPtr=*&arr;
Which compiles but is more complex and is functionally the same thing in this context.
But you may prefer just returning an int* instead of taking a reference to the pointer.
Then when you are done using the array in main(), and set it to NULL just in case you accidentally use it again, like this:
for(int j=0;j<size;j++)
{
cout<<arrPtr[j]<<endl;
}
delete [] arrPtr;
arrPtr = NULL;
Why are you declaring a parameter as 'int *& arrayPtr'? Do you just need a pointer to an array? You should use 'int *arrayPtr' instead.
To answer your question, the problem is that you are declaring an array in the function makeArray's stack. Upon the completion of a function, that function's stack is destroyed, so you're passing the address of junk data. To avoid this, use dynamic memory allocation instead.
EDIT: Also, you should use memset instead of a for loop to zero an array. It's much faster.
The "arr" which you allocate in "makeArray()" is local. and when the functione is over the array is release. When you back to main you get garbage.
What you want to do, is to use the "new" operator to allocate this new array to be used in all program, unless you will free this memory by "delete".
so you can set your makeArray() to:
int* makeArray(int size )
{
int *arr = new[size];
for(int i=0;i<size;i++)
{
arr[i]=0;
}
return arr;
}
the in you main you need to initialize your arry by:
int * arrPtr = makeArray(10);
just don't forget to release this memory after you finsh:
delete[] arrPtr ;
my code:
#include <iostream>
using namespace std;
int main() {
int n=5;
int a[n][n];
a[1][1]=5;
return 0;
}
I got this error when trying to watch the expression a[1][1] in eclipse on line 6:
Failed to execute MI command:
-data-evaluate-expression a[1][1] Error message from debugger back end:
Cannot perform pointer math on
incomplete types, try casting to a
known type, or void *.
i guess it's returned from gdb? however, i don't know why i can't watch that value? Isn't "a" is a normal multi-dimensional array?
For some odd reasons this isn't valid C++ unless you make it
const int n = 5;
Otherwise the array size is formally unknown until runtime.
C++ doesn't suppose variable length array (VLA). So your code is not standard conformant code.
It will not compile if you compile it with g++ -pedantic. The array size must be constant expression. But in your code, its not.
So write:
const int n=5; //now this becomes constant!
int a[n][n]; //the size should be constant expression.
Lets try the above code, as its completely Standard conformant code now.
why not better do it a dynamic 2d array? In that case you do not have to make the n constant, and you can determine the size dynamically.
int **arr, n;
arr = new int * [n]; // allocate the 1st dimension. each location will hole one array
for (i=0; i<n; i++)
{
arr[i] = new int [n]; // allocate the 2nd dimension of one single n element array
// and assign it to the above allocated locations.
}
Now you can access the aray as arr[i][j]
To free to the reverse
for (i=0; i<n; i++)
{
delete [] arr[i]; // first delete all the 2nd dimenstion (arr[i])
}
delete [] arr; // then delete the location arays which held the address of the above (arr)