Why am I getting this Segmentation Fault(core dump)? I was originally told it is because of my pointer p_p_tictactoe = new char*[cols], but what I was told was not right.The purpose of each set of code is commented throughout the code. The code is running, but I am getting this result. I know the for-loop has to be the main problem for this.
Please enter a number of rows: 4
Please enter number of columns: 3
Enter a single character for position( << i << ): a
Enter a single character for position( << j << ): b
Segmentation fault (core dumped)
#include <iostream>
using namespace std;
int main()
{
// TODO: Below each Bp_tictactoe` of type pointer-to-a-pointer-to-a-char
char **p_p_tictactoe;
// 2. Prompt your user to enter a number of rows, then a number of columns.
// store their answers in the variables `rows` and `cols`.
char rows;
char cols;
cout << "Please enter a number of rows: ";
cin >> rows;
cout << "Please enter number of columns: ";
cin >> cols;
// 3. Allocate a 1-dimensional array of pointers-to-chars (length == `rows`)
// and store its address in `p_p_tictactoe`
p_p_tictactoe = new char*[rows];
// 4. Use a for-loop to allocate a dynamic array of chars (length == `cols`)
// for i from 0 to rows - 1 and store its address in `p_p_tictactoe[i]`.
for (int i = 0; i < rows - 1; i++)
{
p_p_tictactoe = new char*[cols];
}
// 5. Use a for-loop to prompt the user to enter a char for each position in
// (" << i << ", " << j << "): "
// As you read each char, store it in the array.
// 6. Use a nested for-loop to print the array, one row per line. The chars
// for each row should be space-separated. For example, if the array is
// 2 x 3 and stores the values A, B, C, X, !, &, the output should look
// like:
// A B C
// X ! &\
char new_input1;
char new_input2;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
cout << "Enter a single character for position( << i << ): ";
cin >> new_input1;
cout << "Enter a single character for position( << j << ): ";
cin >> new_input2;
*p_p_tictactoe[i] = new_input1;
*p_p_tictactoe[j] = new_input2;
cout << *p_p_tictactoe[i] <<endl;
}
}
// *** Prevent memory leaks by deallocating dynamic memory when you are done
// using it. ***
// 7. Use a for-loop to delete each row of the dynamic array.
// 8. Delete the pointer-to-a-pointer to release the array of row pointers,
// and set its value to NULL to avoid accessing invalid memory.
for (int i = 0; i < 3; i++)
{
delete[] p_p_tictactoe[i];
delete[] p_p_tictactoe;
}
cout << "Bye!" << endl;
return 0;
}
among other things, your allocation of p_p_tictactoe is incorrect. This is a double pointer, which simply means it's a pointer to an array of pointers. Your two-step allocation is the correct thought, but what you have in the for loop is incorrect. After the line p_p_tictactoe = new char*[rows], you now have a pointer to an array of char* types. So if rows is 4, what you have in memory now looks like:
p_p_tictactoe[0] == char* --> junk
[1] == char* --> junk
[2] == char* --> junk
[3] == char* --> junk
You now have to loop through each of these 4 char* and allocate space for them. Each char* must point to an array of chars. This is where the comment gives you the hint about looping through and using the p_p_tictactoe[i] indexing:
for (int i = 0; i < rows - 1; i++)
{
p_p_tictactoe[i] = new char[cols];
}
Now, for cols == 3, in memory you have:
p_p_tictactoe[0] == char* --> 3 consecutive bytes
[1] == char* --> 3 consecutive bytes
[2] == char* --> 3 consecutive bytes
[3] == char* --> 3 consecutive bytes
The code you posted is a memory leak. Every time you do p_p_tictactoe = new char*[#], the OS goes to the heap to get enough memory for the assignment. You are not keeping track of the previous pointer nor freeing it first, so that's allocated memory that now has nothing pointing to it.
And the same theory applies to freeing memory. What you have at the end is not quite right. Deallocation is always a mirror image of the allocation. This is clearly a homework assignment, so I won't post that code, but it's the same as the allocation except in reverse.
I'd highly recommend using gdb, which is a text debugger for linux (or any equivalent debugger). If you want any hope of successfully coding in C/C++, you have to learn how memory works on both the stack and heap, and you have to learn how to correctly manage it, or you will be in for a world of hurt. gdb is a little daunting at first, but it will let you print out memory addresses and examine memory which is very helpful for learning and re-enforcing what you think you know.
i think problem here is that you should have taken a double array for the double pointer variable.. you reassigning two different things to one variable..
One problem with your code is that your width and height aren't getting interpreted the way you think they are. When you write this:
char width;
cin >> width;
...the resulting program reads one character and assigns its ASCII value to width. So if you entered '4', then width == 52 would evaluate to true,
and width == 4 would be false. (But width == '4' would be true because '4' == 52).
This problem is easy to fix: Just use int instead of char. You're not saving any memory anyway, because new is probably creating word-aligned pointers.
That's in addition to the problem pointed out by Tarang Gupta.
It is because of the lines:
*p_p_tictactoe[i] = new_input1;
*p_p_tictactoe[j] = new_input2;
You are treating it as an array with 2 dimensions.
the following is written wrongly:
p_p_tictactoe = new char*[rows];
for (int i = 0; i < rows - 1; i++)
{
p_p_tictactoe = new char*[cols];
}
You first allocated a space to p_p_tictactoe of size sizeof (char*[rows]) and replacing its contents with p_p_tictactoe = new char*[cols]; for (int)row times. There is a lot of unused and unreferenced memory in your code.
Even after you change your code to prevent this error, the following will cause problems yet again:
for (int i = 0; i < 3; i++)
{
delete[] p_p_tictactoe[i];
delete[] p_p_tictactoe;
}
You are deleting the space allocated and referenced by p_p_tictactoe 3 times in a row. It should have been outside the loop.
Related
Can someone explain how an array of pointers implementation of c++ dynamically?
Is the below code correct?
If so,
int *ptr[5];
for (int i = 0; i < 5; i++)
{
int size = 2;
ptr[i] = new int [size] ;
//*(ptr + i) = new int[size]; this is the same as above line
cout << &ptr[i] << endl; ----------> line 1
cout << ptr[i] << endl; -----------> line 2
}
What is actually printing in line 1 and 2 ?
this is the addresses i get for line 1
0x7fff88f805d0
0x7fff88f805d8
0x7fff88f805e0
0x7fff88f805e8
0x7fff88f805f0
this is the addresses I get for line 2
0x55f946348ef0
0x55f946349330
0x55f946349360
0x55f946349390
0x55f9463493c0
Can somebody explain this whole mess of pointer arrays.
The picture provides a graphical explanation to the problem if anyone gets
confused with the array of pointers concept with dynamically allocating the array of pointers to new int or any other type array
int *ptr[2]; // statically declared pointer array stack
int p [2];
for (int i = 0; i < 2; i++)
{
int size = 2;
ptr[i] = new int[size];
cout << i << " array of int " << endl;
//*(ptr + i) = new int[size];
for (int j = 0; j < size; j++)
{
cout << "value : " ;
cout << *(ptr[i] + j) ; // <------- this should give 0's as value
//cout << (ptr[i])[j] ; <------ same thing
cout << " address :";
cout << ptr[i] + j << endl; //<----- these are in order as well since it's an array of type int
}
}
0 array of int
value : 0 address :0x564c9ede32c0
value : 0 address :0x564c9ede32c4
value : 0 address :0x564c9ede32c8
1 array of int
value : 0 address :0x564c9ede32e0
value : 0 address :0x564c9ede32e4
value : 0 address :0x564c9ede32e8
I am assuming you want to perform operation on dynamic array like adding element and printing;
Remember:In int *ptr=new int[5]; sizeof(ptr) is 8 bytes on stack memory and array will be stored in heap memory.
We will fetch the element via pointer ptr and every element will be fetched as per type of array (say int ) then ptr will go to 0th index element and read the data of it as int type (only 4 bytes as int is of 4 byte generally) and move to next index till end.
Look into code below:
#include <iostream>
using namespace std;
int main() {
int *ptr=new int[5]; //let size = 5
for(int i=0; i<5;i++){
cin>>ptr[i];
}
for(int i=0; i<5;i++){
cout<<&ptr[i]<<":"; //this will print every element's address per iteration
cout<<ptr[i]<<endl; //this will print every element as per input you gave
}
delete []ptr; //remember it's not delete ptr ask if required
return 0;
}
Now See the the output and dry run yourself you can understand
Output
0x556999c63e70:1
0x556999c63e74:2
0x556999c63e78:3
0x556999c63e7c:4
0x556999c63e80:5
Benefit of dynamic array is you can create dynamic sized array by taking size input as per user choice pass that variable is size of dynamic array
i.e you can change above size=5 to 'N' a variable one .
I think this might help you else you can ask for any further clarification.
I'm trying to create a 2D array of c-strings (for a specific school exercise; I'm forced to use c-strings for practice) using dynamic memory allocation. However, it seems that when accessing and writing to the second index of the array (second sub-array), the actual memory location that's used is the same of the first index.
The code:
#include <iostream>
#include <string>
int main()
{
int n_names; std::string current; const int SPACE_FOR_EACH_NAME = 100;
std::cout << "How many names to input? "; std::cin >> n_names; std::cin.ignore();
//dynamically allocate a multi-dimensional array
char** names;
names = new char* [n_names];
for (int i = 0; i < n_names; i++)
names[i] = new char[SPACE_FOR_EACH_NAME];
int count = 0;
while (count < n_names) {
std::cout << "Name " << ++count << ": ";
std::getline(std::cin, current);
names[count-1] = (char*) current.c_str(); //THE TROUBLE SEEMS TO BE HERE
}
for (int i = 0; i < n_names; ++i) {
for (int j = 0; j < SPACE_FOR_EACH_NAME; ++j) {
if (names[i][j] == '\0') break; //termination of the current name
std::cout << names[i][j];
}
std::cout << "\n";
}
//free allocated memory
for (int i = 0; i < n_names; ++i)
delete[] names[i];
delete[] names;
}
What the debugger shows when modifying the 'names' array (consider user inputs 2 names):
+ names[count-1] 0x00affbe8 "dude" char * //here count is 1
+ names[count-1] 0x00affbe8 "noice" char * //here count is 2
And the console just prints "noice" twice.
What's wrong?
The result of current.c_str() should never be stored for any length of time. Doing so is undefined behaviour, but it is likely, as here that that memory pointed to will be reused.
You put the char* from current.c_str() into names[0], then you put a new value into current and put current.c_str() into names[1]. But because you have changed current you also change names[0].
Also, in both cases, you are discarding the pointer you already created with names[i] = new char[SPACE_FOR_EACH_NAME];
This allocates a block of memory and puts it's address into names[0] (0 as a specific example). The next thing that happens with names[0] is names[0] = (char*) current.c_str(); which puts a different address into the variable. The address returned from the new is lost completely, causing a memory leak.
Instead of
names[count-1] = (char*) current.c_str();
try
std::strcpy(names[count-1],current.c_str())
Could someone explain to me, why there are 4 additional slots in char tab[], when I asked only for 3? How to get rid of them? I'm coding in Visual Studio 2017. Edit: the first program was very basic and didn't show what I intended. So, there is an extended one.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int i, n;
vector<char> input;
char chp;
cout << "Enter a expression" << endl;
while (1)
{
cin.get(chp);
if (chp == '\n') break;
input.push_back(chp);
}
n = input.size();
char* tab = new char[n] {};
for (i = 0; i < n; i++)
{
tab[i] = input[i];
}
int l = strlen(tab);
for (int i = 0; i < l; i++)
{
cout << "tab[" << i << "] is " << tab[i] << endl;
}
cin.get();
}
Result in console window is similar, when I enter "3+3"
tab[0] is 3
tab[1] is +
tab[2] is 3
tab[3] is ř
tab[4] is ř
tab[5] is ř
tab[6] is ř
This isn't still the full program (full program is a calculator, that calculates any math expression, and is much longer). I wrote that in C long time ago, and in C dynamic arrays are not such a problem.
Also, what about multidimensional arrays? Can string be a solution also for them?
Could someone explain to me, why there are 4 additional slots in char tab[], when I asked only for 3?
There aren't. The array has only 3 elements.
The problem is that your array elements have indeterminate values. As a consequence of passing a pointer to array of indeterminate values into strlen, the behaviour of your program is undefined.
Solution: Initialise your array. Furthermore, initialise it so that it contains a null terminator, as required by strlen:
char* tab = new char[3]{'a', 'b', '\0'};
As alternative to null termination, don't use strlen to get the length. You already know that the array contains 3 elements. But the values must still be initialised before you insert them into the output stream.
P.S. Don't forget to delete memory that you allocate:
delete[] tab;
I'm hoping someone can shed some light on where I am going wrong with pointers.. I've read countless web pages and tried various things but for some reason my code is returning jibberish (which I'm guessing may be the memory addresses instead of the data within my array). The purpose of the program is to create an array of 100 elements on the heap, pass this array by a pointer to a function (along with two integer variables start and end); a new array will be created on the heap (this comprises of a chunk of the original array using the start and end variables) and the pointer to this array is passed back to the main method so that the new array can be outputted. My problem is not only is the output seeming to be the location not the value, but also it seems 100 values are outputted not 20 as should be expected. I've spent hours trying to figure out where I have gone wrong and just when I think I understand the concept of pointers my faith is destroyed by red squigglies and incorrect outputs. Please HELP! My code is as follows:
#include "stdafx.h"
#include <iostream>
#include <time.h>
using namespace std;
double* getSubArray(double*, int, int);// Declare a function that will get the sub array
int _tmain(int argc, _TCHAR* argv[])
{
const int size = 100;// Declare the size of the array
double* pA;// Declare the variable to hold the pointers to the data in array
double* pB;
int start = 15;
int end = 35;
pA = new double[size];// Create space for the array
srand(clock());// Seed the program to the computers current time so that random gets a different set of random numbers everytime it is run
// Use a for loop to traverse through each element of the array (starting at index 0) placing a number defined by the random function that is no higher than 250
for (int i = 0; i < size; i++)
{
pA[i] = rand()%250;
}
cout << "An Array of 100 numbers is created and stored in the heap, these values are:" << endl;
// Output the Array for the user to see
for (int j = 0; j < size; j++)
{
// Place 10 numbers on each line
if (j % 10 == 0)
{
cout << endl;
}
cout << *(pA + j) << " ";
}
cout << endl << "The program will build a second array using the data between the indexes " << start << " & " << end << endl;
pB = getSubArray(pA, start, end);// Pass the data to the method
// Output second array for user to compare
for (int k = 0; k < size; k++)
{
// Place 10 numbers on each line
if (k % 10 == 0)
{
cout << endl;
}
cout << *(pB + k) << " ";
}
system("pause");
return 0;
}
double* getSubArray(double* pA, int start, int end)
{
double* pB = new double[end-start];// Declare space in the heap for the new array whoes size is the size of the criteria given
for (int i = 0; i < (end - start); i++)
{
for (int j = start; j < end; j++)
{
*(pB + 0) = pA[j];
}
}
return pB;
}
*(pB + 0) = pA[j];
That keeps writing to the first element of the array. Surely you want to write to each element in turn:
for (int i = start; i < end; ++i) {
pB[i-start] = pA[i];
}
or if you don't want to write your own loop
std::copy(pA+start, pA+end, pB);
Don't forget to delete[] everything you new[] or, to save mucking around with low-level memory management, use std::vector to manage the dynamic arrays for you.
i am new to c++ and i would really appreciate some help with my following problem:
i have dynamically allocated space for a 2d int array of N rows and two columns the following way :
int **input;
input = new int *[N];
for (int count = 0; count < N; count++)
input[count] = new int[2];
when i print its contents in the while-loop in which i "fill" the array the actual contents are printed :
while (!myfileafter.eof())
{
int temp1,temp2;
int i=0;
int j=0;
myfileafter >> temp1>>temp2;
input[i][j]=temp1;
input [i][j+1] = temp2;
i++;
j=0;
cout<<input[i-1][j]<<" "<<input[i-1][j+1]<<endl;
}
// for (int p=0;p<N;p++)
// cout<<input[p][0]<<" "<<input[p][1]<<endl;
however , if i use the two commented-out lines just after the while loop the array seems to contain totally different contents than the right ones printed before and this is the cause of many problems in the rest of the programm . any idea how can this be solved?
It seems that the contents of the file do not match with the length of your array.
Try this:
int temp1,temp2;
int i=0;
int j=0;
while ( i < N && myfileafter >> temp1>> temp2 )
{
input[i][j]=temp1;
input[i][j+1] = temp2;
i++;
j=0;
cout<<input[i-1][j]<<" "<<input[i-1][j+1]<<endl;
}
// Note the termination condition. It is uncertain whether all N locations have been filled.
for (int p=0;p<i;p++)
cout<<input[p][0]<<" "<<input[p][1]<<endl;
EDIT: Instead of using a 2D Nx2 array, I would suggest you to use 2 1D arrays to avoid possible errors and for code clarity. Or better still, use two 1D vectors.
With pointers you will have to take care of deleting the allocating memory.
At the beginning of the loop you set i to zero, so you're always reading into input[0].
It's better to use the actual reading as the condition:
int i = 0;
while ( my_file_after >> input[i][0] >> input[i][1] ) ++i;
The first thing I'd recommend is to practice formatting your code more consistently. There are some accepted conventions that can make your code a lot more readable. Only changing formatting, I'd recommend something like this:
while (!myfileafter.eof())
{
int temp1,temp2;
int i=0;
int j=0;
myfileafter >> temp1 >> temp2;
input[i][j] = temp1;
input [i][j+1] = temp2;
i++;
j=0;
cout << input[i-1][j] << " " << input[i-1][j+1] << endl;
}
//for (int p=0; p < N; p++)
//{
// cout << input[p][0] << " " << input[p][1] << endl;
//}
I'm sure it's also possible that you formatted it correctly and it just got messed up when you entered it here, but proper formatting can make a world of difference.
Moving on... gahh! Carl beat me to it: you're overwriting input[0] every time.
The only thing I'll add is that the cout inside your loop is a bit deceptive because it will print out what you expect it to, but it's printing it from input[0][0] and input[0][1] every time.
Ok, there are other answers here that explain what is wrong with your code specifically, but I'll also add some other information about how you're approaching the array allocation itself.
Typically speaking, an array (unless it's some STL or other intelligent/class array) is a contiguous piece of memory. Then an additional array points to that. In other words, for foo[X][Y] you're creating foo[X] first then adding the [Y] component after the fact, individually, instead of creating a contiguous [X*Y] piece of memory then having each foo[X] element point to the first element of each [Y]. Visually, you're doing this:
foo -|
|
|
| [...]
then each int individually like
foo -| -- _
|_
| -- _
|_
| -- _
|_
| [...]
when you should be allocating the entire int chunk as one piece because 1) if you do a lot of small allocations like this it tends to kill performance (not that important for you here I don't think) and b) pointer arithmetic will actually work if the array is properly created.
Let's say you have the following chunks:
foo is an array of int* that starts at ADDRESS_X and is 4 elements long. For your example you need 4 elements * 2 columns = 8 ints total. So you create a contiguous 8 int long array that starts at ADDRESS_Y. You'd then want to do this (pseudocode-ish here):
int **foo = new int *[SIZE_OF_X]; // an array of 4 pointers
int *bar = new int[SIZE_OF_X * NUMBER_OF_COLUMNS]; // in other words, 8 ints
for (i = 0; i < SIZE_OF_X; i++) {
foo[i] = &bar + (i * SIZE_OF_X);
}
Where bar is:
ADDRESS_Y + 0: 10
ADDRESS_Y + 1: 20
ADDRESS_Y + 2: 30
...
And foo is:
ADDRESS_X + 0: ADDRESS_Y
ADDRESS_X + 1: ADDRESS_Y + 2
...
so foo[1][0] == 30.