Exception thrown when trying to change a pointer in a void function - c++

I am trying to make a void function where it changes the pointer that I pass. The code is throwing an exception on one of the lines and i'm not sure why. Could it be I cannot pass the arrays as pointers then implement math on it? I thought I deallocated the pointers to fix it but this seemed to not work.
Void function:
#include <iostream>
using namespace std;
void* func2(int one, double *value1[], int two, double *value2[], double *final1) {
double testval;
double finalval = 0;
//double *final1;
double final = 0;
for (int i = 1; i < one; i++) {
for (int j = 1; j < two; j++) {
testval = *value1[i] * *value2[j]; //exception thrown (works up to this point)
finalval = testval + finalval;
}
final = finalval + final;
}
*final1 = final;
return 0;
}
Main Function:
int main(){
double *array1 = new double[input1];
double *array2 = new double[input2];
//for loop that takes user input and fills in array1 and array2 with size and a list of values
...
double testval2;
func2(input1, &array1, input2, &array2, &testval2);
cout << testval2 << endl;
delete[] array1;
delete[] array2;
return 0;
I am relatively new to pointers, so my apologies if the code is a little illiterate.

It looks like you want to pass two 1D arrays to func2().
One way to do that is remove the [] from the function signature as
(int one, double *value1, int two, double *value2, double *final1)
Within the function, change *value1[i] to value1[i], and similarly for value2. And remove the & when calling the function from the main().
A couple other thoughts:
I'm not sure how an exception could throw from your code. But *value1[i] is definitely an invalid memory access, so what you may have seen is a segmentation fault message. A helpful tool to troubleshoot these kinds of errors is AddressSanitizer, enabled in clang or gcc by compiling with -fsanitize=address, or if you are using Xcode, there is an option for it. Another great tool is valgrind.
Manually allocating dynamic arrays is a pretty C-like way of using C++. In C++, it is idiomatic to create the arrays as std::vector objects, which under the hood works the same way (it also allocates a dynamic array) but has a more convenient interface. Particularly the vector cleans itself up automatically, so no need to call delete[], and the vector knows its own size, so no need to pass the size around as a separate parameter as with dynamic arrays.
Edit: Here is a note to clarify why the original code manages to compile but fails at runtime.
In the function signature, the combo of both * and [] on double *value1[] makes value1 a pointer to a pointer to double, equivalent to double **value1. In main(), array1 is a double*. When calling the function, &array1 takes the address of that double*, obtaining a double**. So the type matches and the code compiles.
The code fails at runtime on *value1[i]. value1 is a pointer to pointer to doubles, where the inner pointer points to the dynamic array. So what was intended is (*value1)[i] to first dereference the outer pointer, then subscript into the dynamic array. However, in C++, subscripting (a[]) has operator precedence over dereferencing (*a), so it is read in backward order as *(value1[i]). Subscripting the outer pointer value1[i] is invalid for nonzero i, reading memory from somewhere in the stack and arbitrarily interpreting it as a double*. Then the surrounding *( ) attempts to dereference this busted pointer. The machine's memory protection catches this, and the OS sends a "SIGSEGV" signal or similar to the program to kill it.

Related

Segmentary fault with pointer array C++

I get Segmentary fault with this code:
#include <iostream>
using namespace std;
int* arrayCreate(int length){
int *ew[length];
for (int i=0; i<length; i++)
{
*(ew[i])=i;
}
return ew[0];
}
int main(){
int *ptr=arrayCreate(7);
cout << *ptr << endl;
}
And when I tried to change this line
int *ew[length];
into
int *ew = new int[length];
I have error < indirection requires pointer operand ('int' invalid) >
Any one please explain the difference between these two declaration, why I get segmentary fault and how to fix it?
In the first version, you allocate array of pointers on the stack and return an element of that array - which is dead once the function finishes. Accessing this return value means undefined behaviour.
In the second version, you create array of ints (not pointers) on the heap. Thus the syntax error.
What you want is
int* arrayCreate(int length){
int* ew = new int[length];
for (int i=0; i<length; i++)
{
ew[i]=i;
}
return ew;
}
Or better yet, don't use new[], use std::vector, which manages memory for you:
#include <vector>
#include <numeric> //for std::iota
std::vector<int> arrayCreate(int length){
std::vector<int> v (length);
std::iota(v.begin(), v.end(), 0); //you can use your loop as well
return v;
}
int *ew[length];
Problem 1: The size of an array variable must be compile time constant. length is not a compile time constant. Thus, the program is ill-formed.
how to fix it?
If you need an array with dynamic size, you need to allocate dynamically. Simplest solution is to use std::vector.
why I get segmentary fault
Observation: The pointers in ew have indeterminate values. They don't point to any valid object.
*(ew[i])=i;
Problem 2: You indirect through a pointer stored in the array. Since you're indirecting through an invalid pointer, the behaviour of the program is undefined.
Ask yourself: What int object was ew[i] supposed to be pointing to?
how to fix it?
Don't read indeterminate values, and don't indirect through invalid pointers.
int *ew = new int[length];
Here, you create a dynamic array of integers. Array of integers is not an array of pointers. ew is a pointer to an integer. ew is not a pointer to a pointer.
*(ew[i])=i;
Here, you indirect through ew to access ith successor sibling, and then indirect through that sibling. But the first indirection results in an int object and you cannot indirect through an int.
how to fix it?
Don't try to indirect through an int.
Any one please explain the difference between these two declaration
int *ew[length] is an ill-formed and uninitialised array of pointers to int. int* ew is a single pointer to an int, in this case initialised with the address of a first element of a dynamic array of int.
To get memory for your array in C++ you should write:
int *ew = new int[length];
To return the pointer you should write:
return ew;
This means you return pointer to the beginning of array. It should be mentioned that a[i] <=> *(a + i). You can't write *(ew[i]) = i; to assign, but ew[i] = i; will work.
It should also be said that usage of raw pointers is deprecated in modern c++.

void pointer segmentation fault

In order to understand how void pointer works, I wrote a piece of code to test it. However I got the segmentation fault during the runtime and had not clue how to deal with it. The key point here is that, the data are generated inside that function call. You don't know the datatype and how large is that void pointer should be allocated.
#include <iostream>
#include <vector>
int valueAssignment(void *ptr1, void *ptr2){
std::vector<int> vi;
std::vector<double> vb;
int num = 10;
for (size_t i = 0; i < num; i++) {
vi.push_back((int)rand());
vb.push_back((double)rand());
std::cerr <<i<<": "<< vi[i] <<'\t'<<vb[i]<<'\n';
}
for (size_t i = 0; i < num; i++) ((int*)ptr1)[i] = vi[i];
for (size_t i = 0; i < num; i++) ((double*) ptr2)[i] = vb[i];
return num;
}
int main(int argc, char const *argv[]) {
void * intPtr, *doublePtr;
int size;
size = valueAssignment(intPtr,doublePtr);
std::cerr << "/* ------------------- */" << '\n';
for (size_t i = 0; i < size; i++) {
std::cout <<i<<": "<< ((int*)intPtr)[i]<<"," <<((double *)doublePtr)[i]<<std::endl;
}
return 0;
}
We should simply follow the many many recommendations given by experts.
Do not use raw pointers in C++
Do not use raw pointers in C++
Do not use raw pointers in C++
WIth that we woulld already make a huge progress. But then, you want to learn about a void* pointer. The void pointer is a somehow generic pointer that can point to anything. You can also assign other pointer types to a void pointer. Vice versa this is not possible and you need an explicit type cast.
With classes and espcially derived classes you may even lose information by doing such casts.
Legacy C codes often uses void pointers, but that is basically no problem.
In modern C++, void pointers are rarely needed. Maybe mainly to interface with legacy code.
So, now to your special case:
The problem has been mentioned already in many comments. And this has nothing to do with void pointers, but pointers in general. Your pointers are not initialized. They point to somewhere, randomly at some point in memory. And in your subfunction, you are assigning values to those none initalized pointers, writing values to somewhere randomly in memory. Your program will chrash.
So, a pointer needs to point to somewhere defined. To a defined memory region.
You could have written:
int intArray10[10]; // You should not use C-Style plain arrays
double doubleArray10[10]; // You should not use C-Style plain arrays
void* intPtr = intArray10;
void* doublePtr = doubleArray10;
Then your pointer would point to a defined region. And you program would work.
But then you want to define or use somehow the pointer within your function. If the size is known, then you can allocate data with new and assign it to the pointer. The pointer must then be passed as "reference to pointer" or "pointer to pointer". If the size is unknown, it will be more difficult, you need to inform the calling program on the size.
All this is very error prone and should be avoided.
So again: Do not use raw pointer. If you really need them for some ressource management, then use std::unique_ptr or std::shared_ptr.
Or better use STL container in the first place.

Method crashes every time I put the first integer into array. Bad operation?

I have a method which fills the array with integers:
void fill(int* a[], int dim1, int dim2)
{
int intinArray = 0;
for(int i=0;i<dim1;i++)
{
for(int j=0;j<dim2;j++)
{
cin >> intinArray;
a[i][j] = intinArray;
}
}
}
If I declare array in method main() like this:
int** tab;
fill(tab,3,3);
It crashes when I put the first integer in cin. Why? If there's a problem with this line:
a[i][j] = intinArray;
how should I change it?
The fundamental thing wrong with your code is that you declared pointers, but nowhere do you initialize the pointers to point somewhere. You treat the pointer as if it is a regular old 2 dimensional array of integer. So if it's as easy as that, why use pointers?
Given that this is a fundamental in pointer usage and you plainly aren't doing that, the solution is to review working code that uses pointer.
int main()
{
int *p; // uninitialized -- points to who-knows-where
*p = 10; // this is undefined behavior and may crash
}
Take that code and understand why it also may crash. That pointer points to "we don't know", and then you're assigning 10 to a location that is unknown to you, me, and everyone else reading this answer. See the problem? To fix it, you have to initialize the pointer to point somewhere valid, then you can dereference it and assign to it without error.
int main()
{
int *p; // uninitialized -- points to who-knows-where
int x = 20;
p = &x; // this is now ok, since p points to x
*p = 20; // now x changes to 20
}
Your problem is in this code
int** tab; // <- this one
fill(tab,3,3);
You declared a pointer, and are using it under the assumption that it is pointing to allocated memory. (I guess a source of confusion is that with C++ objects this isn't really the case)
A pointer is a pointer - it points to a location in memory. There's no guarantee that the value it points to is valid unless you explicitly make sure it is yourself.
Read PaulMcKenzie's answer for more about pointers.
Try
int tab[x][y] = {{0}};
fill(tab,3,3);
where x and y define your 2D array's width and height. You're going to have to handle bounds checking for your application.
Note that changing {{0}} to a non zero number will not initialize everything to that number.

c++ pointer syntax error

I'm studying for an exam in c++ and i have a question on the past papers
"Write a function in C++ that takes as input an array of doubles and the length of the array, and returns an array twice the length. The first half of the returned array should contain a copy of the contents of the original array. The second half of the returned array should contain the contents of the original array in reverse order."
"The function should have the following prototype: double *copy_and_reverse(double *a, int length);"
since im obviously new to c++ i got stuck in my solution, my code so far is:
double *copy_and_reverse(double *a, int length){
double *b[length*2];
for(int i=0;i<length;i++){
*b[i]=a[i];
}
for(int i=length;i<length*2;i++){
int w=length-1;
*b[i]=a[w];
w--;
}
return *b;
}
int main()
{
double nums[2]={1.23,5.364};
double *pnums=nums;
*pnums=*copy_and_reverse(pnums, 2);
I think i got the core of the method correct but i'm just stuck in the syntax of using pointers, any help is appreciated and if possible a reasoning behind it so i can learn for the exam.
You've got a few problems with this code.
First
double *b[length*2];
Here you're declaring an array of pointers to doubles. The array is of size length * 2, however, none of the pointers in this array are valid yet. This is probably not what you intended to do.
You want an array of doubles, of size length * 2. You can't return an array in C++ but you can return a pointer to some memory that contains an array of doubles.
Let's start by allocating enough memory for all those doubles
double *b= new double[length * 2];
In your first for loop you can treat result as an array
for(int i=0;i<length;i++){
b[i]=a[i];
}
Here you're copying the values from a for each index i to be at the same index. I'll let you figure out how to fill in the reverse part for the second half of the array. You're on the right track, however you might want to think about doing it all in one loop ;)
Your return statement just needs to return your variable b, as it's already a double *.
return b;
An important thing to remember is that you're allocating memory in this function with new. You are responsible for deleting this when you're done with it. Also, when you allocate using new and [] you have to delete using [] as well.
delete [] b;
you can call your function just by de-referencing the first item in your array.
int main() {
double nums[2]={1.23,5.364};
double *pnums = copy_and_reverse(&pnums[0], 2);//don't forget to clean up pnums afterwards!
There are quite many errors in your code. The major one is that you need to allocate new array of doubles. And return that array. I'd suggest compare this with your version line by line:
double *copy_and_reverse(double *a, int length){
double *result = new double[length*2];
for(int i=0;i<length;i++) {
result[i]=a[i];
}
int r = length*2;
for(int i=0; i < length;i++){
result[--r]=a[i];
}
return result;
}
And your main() shall look like:
int main()
{
double nums[2]={1.23,5.364};
double *pnums = copy_and_reverse(nums, 2);
...
delete[] pnums;
}
Ok, there are at least two problems with this:
double *b[length*2];
The first problem is that you are declaring a local array (of pointers), which you will then try to return:
return *b;
(You're returning the wrong thing here, too, but that's another story) You can't return a pointer to a locally-allocated thing because as soon as the function returns, the locally-allocated thing will be destroyed. Instead, given that you must return a pointer to the first element of an array, you have to dynamically allocate that thing using new.
Second, you can't declare an array like this using a length which s only known at runtime. But this problem will be obviated when you use new to dynamically allocate the array.
I would normally say that you shouldn't be doing any of this at all, and just use a std::vector -- but clearly a requirement of this assignment is to use a dynamically allocated C-style array. (Which I take great issue with your professor on.)
I would also say that the prototype:
double *copy_and_reverse(double *a, int length);
doesn't declare a function which takes an array, as your professor incorrectly asserts, but a function which takes a pointer to a double. That that pointer is the first element in an array doesn't magically make a an array. In short: an array and a pointer are not the same thing.
These last two observations are just for your benefit.
I assume this is not your homework and I am trying to help you out.
Look at the comment of code.
double *copy_and_reverse(double *a, int length)
{
double * b = new double[length*2]; //create a new array using new[]
for(int i=0;i<length;i++){
b[i]=a[i]; //addressing element with []
}
int w=length-1; //I assume this is what you want
for(int i=length;i<length*2;i++){
b[i]=a[w];
w--;
}
return b;
}
int main()
{
double nums[2]={1.23,5.364};
double *pnums = copy_and_reverse(nums, 2);
delete[] pnums;
}
Also noted the memory is allocated in the function, so in the main, you want to delete it by using [].

Scope, arrays, and the heap

So, I have this array. It needs to be accessed outside the scope of this function. I have been slapping a pointer to it into a pair which gets put into a deque. But once I'm outside the scope, the local stack is gone, the array is invalid, and I've just got a useless pointer, right?
So I've trying to put this array onto the scope-transcending heap, where it will remain until I delete it at a later time. But I'm having issues getting this working. Right now g++ is coughing up errors about invalid conversion from 'int' to 'int*'.
void randomFunction(int x, int y, int width, int height)
{
int **blah[4] = {x, y, width, height};
std::pair <foobar*, int* > tempPair (foobar1, blah);
randomDeque.push_front(tempPair);
}
I've also tried initializing it like this:
int *blah[4] = new int[4];
...and it says that the array must be initialized with a brace-enclosed initializer.
I'm really not used to working with pointers. What am I doing wrong?
There are two problems. First, indeed, you are confused about pointers/arrays:
int a[4]; // this is an array of 4 integers, a is the name of the array
int *a[4]; // This is an array of 4 *pointers* to int
So your declaration:
int **blah[4];
Define an array of 4 pointers to pointers array. Maybe you are confused by the following fact (I know I was when I learned C). If you declare a variable:
int *a;
This is a declaration of a pointer to an integer. But if you have a variable a which is a pointer, you get the thing it points to (an integer here) by using *a:
*a = 1; // a is a pointer (i.e. an address), *a is the value pointed to by a.
So * in declaration is used to declare pointer, but * in statements is used to deference value.
But your second problem has nothing to do with pointer per-se. It is about ressource-management (memory being one, but file, locks being others). Anything allocated on the stack does not exist anymore when it is out of scope. In pure C, you only really have one solution: allocating on the heap with malloc, and making sure to free afterwards. So you would do something like:
// foo is a struct
foo *init_foo()
{
foo* tmp;
tmp = malloc(sizeof(*tmp));
// initialize tmp
return tmp;
}
And then, you will clean it with another function:
foo *a;
a = init_foo();
// do stuff
clean_foo(a);
Example: the FILE* handle and fopen/fclose (in addition to allocating stuff, there are some things related to the OS to handle the file). Another solution is to use alloca, which is not standard C, but is supported by many toolchains.
In C++, you can use smart pointers, which use for example reference counting to do resources management. I am less familiar with C++, and I am sure people will jump in on that part. The idea with reference counting is that it still gives some of the advantages of auto pointers (you don't have to call delete by yourself, which is extremely error-prone for non trivial projects), but without being purely scope-based. One reference counting-based smart pointer is shared_ptr in boost.
The whole concept looks strange to me. If you declare array on the stack, it will not exist outside the scope of your function. If you allocate it using 'new' - make sure you 'delete' it sometime, otherwise it's memory leak!
The correct code with 'new' is:
int *blah = new int[4];
...
// don't forget to:
delete [] blah;
I'm not sure if I got right what you want to do, but in case you want to return a reference to an int array which will be valid after randomFunction returns, a good way to do it is with Boost:
#include <boost/shared_ptr.hpp>
#include <vector>
boost::shared_ptr<std::vector<int> > randomFunction(int x, int y, int width, int height)
{
boost::shared_ptr<std::vector<int> > blahPtr(new std::vector<int>(4));
(*blahPtr)[0] = x;
(*blahPtr)[1] = y;
(*blahPtr)[2] = width;
(*blahPtr)[3] = height;
return blahPtr;
}
You don't have to remember about deleteing blahPtr -- when all copies of it go out of scope, Boost will delete your std::vector object automatically, and C++ standard library will delete the underlying array.
It looks like you want a 4x4 array, in which case you should create it like so (untested code from the top of my head):
int **blah = new int* [4];
for(int i = 0; i < 4; ++i)
{
*blah[i] = new int[4];
}
Alternatively you can create a 1D array and treat it like a 2D array:
int *blah = new int[16];
#define ELEM(x,y) w*4+h
blah[ELEM(1,1)] = 123;