Why am I getting *** glibc detected *** free(): invalid pointer error? - c++

I am getting this error on my delete[] in my code below
string lcs_tree(string sig, string flow)
{
int l1, l2;
string getres;
l1 = sig.length()+1;
l2 = flow.length()+1;
char *x, *y;
x = new char [l1];
y = new char [l2];
x = (char*)sig.c_str();
y = (char*)flow.c_str();
lcs_length(x, y, l1, l2, getres);
delete[] x;
delete[] y;
return getres;
}
I'm trying to make the delete to free up memory because my program keeps getting killed when I don't free up memory after dynamically creating arrays. My delete works for this section of the code
void lcs_length(char *x,char *y, int l1, int l2, string& getres)
{
int m,n,i,j,**c;
c = new int *[l1];
for(int t = 0; t < l1; t++)
c[t] = new int [l2];
char **b;
b = new char *[l1];
for(int t = 0; t < l1; t++)
b[t] = new char [l2];
m=strlen(x);
n=strlen(y);
for(i=0;i<=m;i++)
c[i][0]=0;
for(i=0;i<=n;i++)
c[0][i]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(x[i-1]==y[j-1])
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]='c'; //c stands for left upright cross
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]='u'; //u stands for upright or above
}
else
{
c[i][j]=c[i][j-1];
b[i][j]='l'; //l stands for left
}
}
print_lcs(b,x,m,n,getres);
for(int t = 0; t < l1; t++)
delete[] c[t];
delete[] c;
for(int t = 0; t < l1; t++)
delete[] b[t];
delete[] b;
}
But when I use it in the first section I am getting the invalid pointer error. Why am I getting it there and not the second section?

Related

Function which copies an array of integers from one array to another using pointers in C++

The purpose of the Copy function in the following code is to copy an array of integers from one array to another using C++ but the output seems wrong.
What could be the problem here?
#include <iostream>
using namespace std;
void Copy(int old_array[],int new_array[],int length)
{
int *ptr1 = old_array;
int *ptr2 = new_array;
int i = 0;
for(int i=0 ; i<length ; i++)
{
*(ptr2++) = *(ptr1++);
}
for (int i = 0; i <2; i++)
{
cout<<*(ptr2 + i)<<endl;
}
}
int main()
{
int a[2]={0,1};
int b[2];
Copy(a,b,2);
}
This is the output:
ptr2 is one past the end of the array when your print loop runs.
Try this:
void Copy(int old_array[], int new_array[], int length)
{
int* ptr1 = old_array;
int* ptr2 = new_array;
int i = 0;
for (int i = 0; i < length; i++)
{
*(ptr2++) = *(ptr1++);
}
ptr2 = new_array;
for (int i = 0; i < 2; i++)
{
cout << *(ptr2 + i) << endl;
}
}
Your ptr2 is pointing to the element b[2] (which is out-of-bound access) at the time you are printing it in the second for loop.
You can fix it by subtracting the length from the ptr2 in the second for loop like below.
#include <iostream>
using namespace std;
void Copy(int old_array[],int new_array[],int length)
{
int *ptr1 = old_array;
int *ptr2 = new_array;
int i = 0;
for(int i=0 ; i<length ; i++)
{
*(ptr2++) = *(ptr1++);
}
for (int i = 0; i <2; i++)
{
cout<<*(ptr2 + i - length)<<endl;
}
}
int main()
{
int a[2]={0,1};
int b[2];
Copy(a,b,2);
}
The copy seems fine but the second for is accessing ptr2 which was incremented in the first for and is point to some invalid memory position. You could use new_array in this second loop.
I suppose this second loop is only for debug and will be better located in the main using, in you case, the variable b.

Error in running an implementation of list

This is the part of the code where I'm facing the problem:
#include<iostream>
using namespace std;
struct ID{
int value;
ID *nxtElement;
};
struct SqLand{
ID *id;
SqLand *next;
};
int main(){
for(int p, i = 0; i < 3; i++){
SqLand *nptr = new SqLand;
cin >> p;
ID *buff = new ID;
buff = nptr->id;
for(int j = 0; j < p; j++){
cin >> buff->value;
//cout << "Garbage";
buff = buff->nxtElement;
}
buff = NULL;
//cout << "WILL";
delete nptr;
delete buff;
}
return 0;
}
The problem is that on running this program and inserting the value of p more than 1, the program exits after 2 more inputs.
For example, starting like this:
2
1
3
This is where the program exits
If both the cout statements are un-commented here are the outputs:
2
1
Garbage3
GarbageWILL
And another:
3
1
Garbage2
Garbage
All the programs exit after their respective last lines. What is the error in my program? It's a part of another program so that don't expect this snippet to make any sense. I only want to know where it goes wrong.
What i can understand from your code this ... (with fix)
struct ID {
ID(int val = -1, ID* _nxtElement = NULL) :
value(val), nxtElement(_nxtElement) {
}
int value;
ID *nxtElement;
};
struct SqLand {
SqLand(ID* _id = NULL, SqLand* _next = NULL) :
id(_id), next(_next) {
}
ID *id;
SqLand *next;
};
const int size = 3;
int main() {
SqLand* head = new SqLand;
SqLand* tmp = head;
for (int p, i = 0; i < size; i++) {
cin >> p;
tmp->id = new ID;
ID* tmpID = tmp->id;
for (int j = 0; j < p; j++) {
cin >> tmpID->value;
// avoid unnecessary allocate
if (j < p - 1) {
tmpID->nxtElement = new ID;
tmpID = tmpID->nxtElement;
}
}
// avoid unnecessary allocate
if(i < size - 1) {
tmp->next = new SqLand;
tmp = tmp->next;
}
}
return 0;
}
in your code you miss allocate for nptr->id and you miss the most important the head of list (SqLand *nptr = new SqLand;).

how do I allocate one block of memory with new?

I have a two dimensional array that I've allocated dynamically using new.
The problem is I want to allocate the memory as one connected block instead of in separated pieces to increase processing speed.
Does anyone know if it's possible to do this with new, or do I have to use malloc?
Here's my code:
A = new double*[m];
for (int i=0;i<m;i++)
{
A[i]= new double[n];
}
This code causes a segmentation fault
phi = new double**[xlength];
phi[0] = new double*[xlength*ylength];
phi[0][0] = new double[xlength*ylength*tlength];
for (int i=0;i<xlength;i++)
{
for (int j=0;j<ylength;j++)
{
phi[i][j] = phi[0][0] + (ylength*i+j)*tlength;
}
phi[i] = phi[0] + ylength*i;
}
You can allocate one big block and use it appropriately, something like this:
double* A = new double[m*n];
for (int i=0; i<m; i++) {
for (int j=0; j<n; j++) {
A[i*n+j] = <my_value>;
}
}
Instead of using new, you can use malloc - there is no much difference, except that new must be released with delete, and malloc() released with free().
UPDATE1:
You can create "true" 2d array as follows:
double** A = new double*[m];
double* B = new double[m*n];
for (int i=0; i<m; i++) {
A[i] = B + n*i;
}
for (int i=0; i<m; i++) {
for (int j=0; j<n; j++) {
A[i][j] = <my_value>;
}
}
Just be sure to release both A and B in the end.
UPDATE2:
By popular request, this is how you can create "true" 3-dimensional array (with dimensions m x n x o):
double*** A = new double**[m];
double** B = new double*[m*n];
double* C = new double[m*n*o];
for (int i=0; i<m; i++) {
for (int j=0; j<n; j++) {
B[n*i+j] = C + (n*i+j)*o;
}
A[i] = B + n*i;
}
for (int i=0; i<m; i++) {
for (int j=0; j<n; j++) {
for (int k=0; k<o; k++) {
A[i][j][k] = <my_value>;
}
}
}
This uses 2 relatively small "index" arrays A and B, and data array C. As usual, all three should be released after use.
Extending this for more dimensions is left as an exercise for the reader.
There is nothing you can do with malloc that you can't do with new (though the converse doesn't hold). However if you've already allocated the memory in separate blocks, you will have to allocate new (contiguous) memory in order to get a connected block (with either malloc or new). The code you show allocates m non-contiguous n-sized blocks. To get an array with contiguous memory from this, you would need
int MN = m*n;
B = new double[MN];
for (int i=0; i<MN; ++i)
B[i] = A[ i/N ] [ i%N ];
Ok, if the task is to maintain a single block of memory, but keep [][] way of addressing it, I'd try a few tricks with classes. The first one is an inside proxy:
class CoordProxy
{
private:
int coordX;
int arrayWidth;
int * dataArray;
public:
CoordProxy(int * newArray, int newArrayWidth, int newCoordX)
{
coordX = newCoordX;
arrayWidth = newArrayWidth;
dataArray = newArray;
}
int & operator [](int newCoordY)
{
return (dataArray[newCoordY * arrayWidth + coordX]);
}
};
class CoordsWrapper
{
private:
int * dataArray;
int width;
int height;
public:
CoordsWrapper(int * newArray, int newWidth, int newHeight)
{
dataArray = newArray;
width = newWidth;
height = newHeight;
}
CoordProxy operator[] (int coordX)
{
return CoordProxy(dataArray, width, coordX);
}
};
int main(int argc, char * argv[])
{
int * a = new int[4 * 4];
ZeroMemory(a, 4 * 4 * sizeof(int));
CoordsWrapper w(a, 4, 4);
w[0][0] = 10;
w[0][1] = 20;
w[3][3] = 30;
std::for_each(&a[0], &a[4 * 4], [](int x) { printf("%d ", x); });
delete[] a;
}
Note, that this is not time-efficient, but extremely memory efficient: uses 4 ints and 2 pointers more than original class.
There's even nicer and a lot faster solution, but you would have to resign from [][] notation in favor of (,) notation:
class CoordsWrapper2
{
private:
int * data;
int width;
int height;
public:
CoordsWrapper2(int * newData, int newWidth, int newHeight)
{
data = newData;
width = newWidth;
height = newHeight;
}
inline int & Data(int x, int y)
{
return data[y * width + x];
}
};
int main(int argc, char * argv[])
{
int * a = new int[4 * 4];
ZeroMemory(a, 4 * 4 * sizeof(int));
CoordsWrapper2 w(a, 4, 4);
w.Data(0, 0) = 10;
w.Data(0, 1) = 20;
w.Data(3, 3) = 30;
std::for_each(&a[0], &a[4 * 4], [](int x) { printf("%d ", x); });
delete[] a;
}
Note the inline directive. It suggests the compiler to replace the method call for actual source code, which make it a little faster. This solution is even more memory efficient and a either a tiny bit less or equally time efficient as classic indexing.

Declaration and assignation of dynamic 3d array

I have made the next class for a 3d array. Declaring a variable as, for example
Grid3d n = Grid3d(2,2,2);
n(0,0,0) = 1;
works fine, but declaring it as
Grid3d n;
n = Grid3d(2,2,2);
n(0,0,0) = 1;
Gives me a segmentation fault, the problem seems to be the default constructor, but i don't know how to fix it, any clue?
#ifndef _GRID3D_
#define _GRID3D_
#include <iostream>
#include <cmath>
#include <cassert> // assert()
using namespace std;
class Grid3d
{
private:
int L;
int M;
int N;
double *** G;
public:
Grid3d(int,int,int);
Grid3d();
Grid3d(const Grid3d &);
~Grid3d();
double & operator()(int,int,int);
};
#endif
//Constructor
Grid3d::Grid3d(int L,int M,int N)
:L(L), M(M), N(N)
{
int i,j,k;
G = new double ** [L];
for (i=0;i<L;i++){
G[i] = new double * [M];
for (j=0;j<M;j++){
G[i][j] = new double [N];
for (k=0;k<N;k++){
G[i][j][k] = 0;
}
}
}
}
//Constructor vacĂ­o
Grid3d::Grid3d()
:L(0), M(0), N(0)
{
G = NULL;
}
//Constructor copia
Grid3d::Grid3d(const Grid3d &A)
:L(A.L), M(A.M), N(A.N)
{
G = new double ** [L];
int i,j,k;
for (i=0;i<L;i++){
G[i] = new double * [M];
for (j=0;j<M;i++){
G[i][j] = new double [N];
for (k=0;k<N;k++){
G[i][j][k] = A.G[i][j][k];
}
}
}
}
//Destructor
Grid3d::~Grid3d()
{
// Libera memoria
for (int i=0;i<L;i++){
for (int j=0;j<M;j++){
delete [] G[i][j];
G[i][j] = NULL;
}
delete [] G[i];
G[i] = NULL;
}
delete G;
G = NULL;
}
double& Grid3d::operator()(int i,int j,int k)
{
assert(i >= 0 && i < L);
assert(j >= 0 && j < M);
assert(k >= 0 && k < N);
return G[i][j][k];
}
Assignment operator
Grid3d Grid3d::operator = (const Grid3d &A)
{
if (this == &A) {return *this;};
if (G != NULL){
// Libera memoria
for (int i=0;i<L;i++){
for (int j=0;j<M;j++){
delete [] G[i][j];
G[i][j] = NULL;
}
delete [] G[i];
G[i] = NULL;
}
delete G;
G = NULL;
}
L = A.L;
M = A.M;
N = A.N;
G = new double ** [L];
int i,j,k;
for (i=0;i<L;i++){
G[i] = new double * [M];
for (j=0;j<M;i++){
G[i][j] = new double [N];
for (k=0;k<N;k++){
G[i][j][k] = A.G[i][j][k];
}
}
}
return *this;
}
You have dynamically allocated memory, but you have not followed the rule of three. You are missing an assignment operator, so when you do this:
Grid3d n;
n = Grid3d(2,2,2); // both RHS temporary and n point to the same data.
n(0,0,0) = 1; // Accessing deleted memory: undefined behaviour.
you will have two attempted de-allocations of the same memory, because you have n's pointer pointing to the same memory as the temporary used to assign to it in the second line. When the temporary dies, it de-allocated it's memory. When n dies, it tries to de-allocate the same memory. Furthermore, any access to that memory after the second line is undefined behaviour.
It's a trivial typo. I'll point out the line, and I'll let you spot where it's gone wrong:
for (j=0;j<M;i++)
That is, aside from the missing assignment operator, which makes the original constructed object in n = Grid3d(2,2,2); be freed, and thus you are accessing G[i][j][k] in operator() with NULL pointers.

double pointer memory allocation

I am currently trying to allocate the same amount of memory for a double pointer. I take in a char** and want to use a bubble sort on that char** . So I create a temp char** and now I'm wondering how to correctly allocate enough memory so that I can return that temp char** to another method.
I know the way I'm allocating right now doesn't look right and it certainly doesn't work...otherwise I wouldn't be asking this question. If someone could respond with some helpful advice, I would greatly appreciate it!
char** bubble_sort(char **filenames, int n)
{
int i;
char **new_list;
new_list = malloc(sizeof(filenames));
for (i = 0; i < n; i++)
{
// malloc(file_list.size * sizeof(int));
new_list[i] = filenames[i];
}
for (i = 0; i < n; i++)
{
printf("%d: %s\n", i, new_list[i]);
}
int x;
int y;
for(x=0; x<n; x++)
{
for(y=0; y<n-1; y++)
{
if(new_list[y]>new_list[y+1])
{
char *temp = new_list[y+1];
new_list[y+1] = new_list[y];
new_list[y] = temp;
}
}
}
for (i = 0; i < n; i++)
{
printf("%d: %s\n", i, new_list[i]);
}
return new_list;
}
char** bubble_sort(char **filenames, int n)
{
int i;
char **new_list;
new_list = malloc(sizeof(filenames));
This code allocates enough space to store a single pointer (sizeof(filenames) is mostly likely 4), and gives the address of that pointer to new_list. If you want to access what new_list points to as an array (and I know you do, because you tried to do just that below), you'll need to allocate enough space for its elements.
Here is the working copy of the program:
#include <cstdio>
#include <cstdlib>
#include <cstring>
char** bubble_sort(const char **filenames, int n)
{
int i;
char **new_list;
new_list = (char**) malloc(sizeof(*new_list) * n);
for (i = 0; i < n; i++)
{
new_list[i] = (char*) filenames[i];
}
printf("Initial list:\n");
for (i = 0; i < n; i++)
{
printf("%d: %s\n", i, new_list[i]);
}
int x;
int y;
printf("List is sorted:\n");
for(x=0; x<n; x++)
{
for(y=0; y<n-1; y++)
{
if(strcmp(new_list[y],new_list[y+1])>0)
{
char *temp = new_list[y+1];
new_list[y+1] = new_list[y];
new_list[y] = temp;
}
}
}
for (i = 0; i < n; i++)
{
printf("%d: %s\n", i, new_list[i]);
}
return new_list;
}
int main(){
const char *ar[5]={
"eee", "aaa", "bbb", "ccc", "ddd",
};
bubble_sort(ar, 5);
return (0);
}
Still, keep in mind that your programming style resembles more to C than C++ (which is not always a bad thing).
If you want to allocate new strings for your array elements, you should change the first for like this:
for (i = 0; i < n; i++)
{
//new_list[i] = (char*) filenames[i];
new_list[i] = (char*) malloc(sizeof(**new_list) * (strlen(filenames[i]) + 1));
strcpy(new_list[i], filenames[i]);
}
And this is the C version (first one was the C++ version). Note that the string array has all its elements newly allocated, and is not using the initial strings from the input parameter.:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** bubble_sort(char **filenames, int n)
{
int i;
char **new_list;
new_list = malloc(sizeof(*new_list) * n);
for (i = 0; i < n; i++)
{
//new_list[i] = (char*) filenames[i];
new_list[i] = malloc(sizeof(**new_list) * (strlen(filenames[i]) + 1));
strcpy(new_list[i], filenames[i]);
}
printf("Initial list:\n");
for (i = 0; i < n; i++)
{
printf("%d: %s\n", i, new_list[i]);
}
int x;
int y;
printf("List is sorted:\n");
for(x=0; x<n; x++)
{
for(y=0; y<n-1; y++)
{
if(strcmp(new_list[y],new_list[y+1])>0)
{
char *temp = new_list[y+1];
new_list[y+1] = new_list[y];
new_list[y] = temp;
}
}
}
for (i = 0; i < n; i++)
{
printf("%d: %s\n", i, new_list[i]);
}
return new_list;
}
int main(){
char *ar[5]={
"eee", "aaa", "bbb", "ccc", "ddd",
};
bubble_sort(ar, 5);
return (0);
}
filenames is a pointer to pointer to char, therefore on this line...
new_list = malloc(sizeof(filenames));
...you're allocating the amount of the size of the pointer (to pointer), which isn't what you want.
You probably want malloc(sizeof(filenames) * n); which will give you the space for n pointers.
This is somewhat of a duplicate. See: Creating `char ***data`?
There are serious memory performance issues with respect to allocating at char** for a 2D array. Better to use a char* and a indexing scheme. In this way you get a contiguous chunk of memory. You can also use a one-D std::vector with such a scheme.
If you must allocate a char**, the for loop is all you can do AFAIK. But at least make a subroutine out of that! :)