I'm currently working on finding the sum of squared distances of two matricies, the data is held in double* arrays. the first of them stays the same while the other is cycled through using a function that returns a 32x32 array between two indices.
However when i try and call "getTile(d,e)" after the first incrementation of "e" it throws a heap corruption exception:
double* Matrix::ssd(int i, int j, Matrix& rhs){
double sum = 0, val = 0; int g = 0, h=0;
double* bestMatch = new double[32*32]; double* sameTile = new double[32*32]; double* changeTile = new double[32*32];
for(int x = i-32; x <i; x++){
for(int y = j-32; y <j; y++){
sameTile[g*32+h] = data[x*N+y];
h++;
}g++; h = 0;
}
system("pause");
for(int d = 32; d<=512; d+=32){
for(int e = 32; e<=512; e+=32){
changeTile = rhs.getTile(d,e);
for(int out = 0; out < 32; out++){
for(int in = 0; in < 32; in++){
val = sameTile[out*32+in] - changeTile[out*32+in];
val = val*val;
sum = sum + val;
}
}
cout << sum << endl;
sum = 0; val = 0;
system("pause");
}
}
The getTile(int i, int j) function:
double* Matrix::getTile(int i, int j){
double* tile = new double[32*32]; int g = 0; int h = 0;
for(int x=i-32; x<i; x++){
for(int y=j-32; y<j; y++){
tile[g*32+h] = data[x*N+y];
h++;
}
cout << endl;
g++;
}
return tile;
}
I believe the error occurs with the allocation of memory in the changeTile double*?
Any help would be very much appreciated.
There are a bunch of issues in your code all related to improperly accessing array elements.
In the first loop the line:
sameTile[g*32+h] = data[x*N+y];
at the very least underflows the data array. Consider if i=0, j=0, and N=512 then you are trying to access data[-16416] in the first pass of the loop.
Second issue is the getTile() method where you forget to reset h to 0 at the end of the inner loop (like you do in the ssd() method). This results in the overflow of tile[]
I would also double-check the line:
changeTile = rhs.getTile(d, e);
and the method getTile() to ensure an array overflow doesn't occur on data[].
Overall I would suggest using proper std:: containers if at all possible. Using them correctly should completely eliminate this type of error. If you really do need to use raw pointers/arrays then you need to make sure all your indexing into them is as clear as possible in addition to bounds checking where needed.
Related
I am trying to create a merge function for two array structures in c++ but am coming up with a bad access error that I don't know how to solve. The error comes up when I am trying to swap the element in the smaller array into the larger, merged array. The code doesn't even go through a single iteration. All three of i, j, and k remain at 0. Any help would be greatly appreciated! Here is the code:
struct Array
{
int *A;
int size;
int length;
};
void display(Array arr){
for (int i = 0; i < arr.length; i++)
std::cout << arr.A[i] << std::endl;
}
Array merge(Array arr1, Array arr2){
Array arr3;
arr3.length = arr1.length + arr2.length;
arr3.size = arr1.length + arr2.length;
int i = 0, j =0, k =0;
while(i <arr1.length && j < arr2.length){
if (arr1.A[i] < arr2.A[j])
{
arr3.A[k] = arr1.A[i]; //(The error is displayed here: Thread 1: EXC_BAD_ACCESS (code=1, address=0x28))
k++;
i++;
}
else if (arr2.A[j] < arr1.A[i])
{
arr3.A[k] = arr2.A[j];
k++;
j++;
}
}
for (; i< arr1.length; i++)
{
arr3.A[k]=arr1.A[i];
k++;
}
for (; i< arr2.length; j++)
{
arr3.A[k]=arr2.A[j];
k++;
}
return arr3;
}
int main() {
Array arr1;
arr1.size = 10;
arr1.length = 5;
arr1.A = new int[arr1.size];
arr1.A[0]= 2;
arr1.A[1]= 6;
arr1.A[2]= 10;
arr1.A[3]= 15;
arr1.A[4]= 25;
Array arr2;
arr2.size = 10;
arr2.length = 5;
arr2.A = new int[arr2.size];
arr2.A[0]= 3;
arr2.A[1]= 4;
arr2.A[2]= 7;
arr2.A[3]= 18;
arr2.A[4]= 20;
Array arr3 = merge(arr1, arr2);
display(arr3);
return 0;
}
Your Array arr3 does not allocate any memory for its int *A field. It's natural that it would not work.
Anyway, your implementation of Array is very poor. Don't reimplement arrays unless you have a good reason; use std::vector instead.
If you really need to implement an Array on your own, then learn about encapsulation, make a class with a constructor, and allocate/delete your data (*A) field properly. Remember, using pointers and heap memory without understanding them is a recipe for disaster.
Easy: arr3.A is not initialized. It's a pointer. What does it point to?
Suggestion: learn about dynamic memory allocation.
I'm writing a simple program within which a dynamic array is to be created. The function that is being used to create said array is in a second .cpp file, attached as a user-made library. Unfortunatelly Visual Studio pops an error saying that the program can't use uninitialized variable. I feel like it's a really easy problem to solve, but I don't know how to get through it. Here is the code:
int main()
{
int i = 5, j = 6;
string** Array;
createDefStruct(Array, i, j);
/*for (int k = 0; k < i; k++)
{
for (int m = 0; m < j; m++)
{
Array[i][j] = "YIKES";
cout << Array[i][j] << '\t';
}
cout << endl;
}*/
deleteDefStruct(Array, i);
return 0;
}
The createDefStruct function:
void createDefStruct(string** Arr, int varAttribCount, int varCount)
{
Arr = new string * [varAttribCount+1];
for (int i = 0; i < varAttribCount+1; i++)
Arr[i] = new string[varCount];
}
How do I go about initilizing a variable?
Thank you in advance!
So the problem is that instead of returning your array from the function you passed the array into the function as parameter. This mean that the variable is uninitialised in main (even though it is initiialised in createDefStruct). Rewrite like this
string** createDefStruct(int varAttribCount, int varCount)
{
string** Arr = new string * [varAttribCount+1];
for (int i = 0; i < varAttribCount+1; i++)
Arr[i] = new string[varCount];
return Arr;
}
int main()
{
int i = 5, j = 6;
string** Array = createDefStruct(i, j);
...
In general when you want a function to return a value you use return from inside the function to return that value. When you want to pass a value into a function you use a parameter. In your createDefStruct function varAttribCount and varCount are the parameters but the array should be a return value.
So I have a program, which helps me finding a cycles in graph by adjacency matrix. I have done everything, except output.
Realization
So, upon clicking exectute button, from masked edit control, an number up to 99 taken to for making a size of some arrays. Then I am creating 2d array **arr to fill it with zeros, and after that via for I fill info from text written in normal edit control. After this step I fill vector with edges from that array and doing DFS for that graph.
Now about problem
Like I said, I have 2d array. The whole procedure of filling it with zeros:
int **arr;
arr = new int* [x];
for (int i = 0; i < x; i++)
{
arr[i] = new int[x];
}
for (int i = 0; i < x; i++)
{
for (int j = 0; j < x; j++)
{
arr[i][j] = 0;
}
}
And with the next procedure (taking adjacency matrix from edit control) lies the warning #1:
int i = 0, j;
int lpos = 0;
for (CString line = s.Tokenize(_T("\r\n"), lpos); lpos > 0; line = s.Tokenize(_T("\r\n"), lpos))
{
j = 0;
int cpos = 0;
for (CString cell = line.Tokenize(_T(" "), cpos); cpos > 0; cell = line.Tokenize(_T(" "), cpos))
{
int num;
num = _wtoi(cell);
arr[i][j] = num;
j++;
}
i++;
}
Warning C6386 Buffer overrun while writing to 'arr[i]': the writable size is 'x*4' bytes, but '8' bytes might be written.
And before making output, I also put in another vector cycles and it also has warning #2:
for (int i = 1; i <= edges; i++) {
if (mark[i] != 0) {
int k = mark[i];
cycles[k].push_back(i);
}
}
Warning C6385 Reading invalid data from 'mark': the readable size is 'x*4' bytes, but '8' bytes may be read.
The problem is, when I tested output (adjacency matrix 7x7, all filled with 1), it catches an exception for those 2 pieces, which is being warnings. The exceptions is: Exception thrown at 0x00007FF6DD63AD7A in CTabControl.exe: 0xC0000005: Access violation writing location 0x00000000FDFDFDFD.
What I tried
For now, I tried to use make_unique pointer as an alterative for * pointer on mark, which was declared previously like this: int *mark = new int[x]; (changed to auto mark = make_unique<int[]>(x);). After change, there is a new error appear:
E0413 no suitable conversion function from "std::unique_ptr<int [], std::default_delete<int []>>" to "int *" exists
It points out to the function, where I use mark array: dfs_cycle(1, 0, color, mark, par, cyclenumber);
The function declared like this:
void dfs_cycle(int u, int p, int color[], int mark[], int par[], int& cyclenumber)
{
// ........
}
What can I do here to fix that?
EDIT
I think I found the problem, yet for now I can't find a solution. So, when the text is being read from text box, where adjacency matrix is, I am filling up the array with the contents of tokenized text. Here's how I am doing it:
int i = 0, j; int lpos = 0;
for (CString line = s.Tokenize(_T("\r\n"), lpos); lpos > 0; line = s.Tokenize(_T("\r\n"), lpos)){
j = 0;
int cpos = 0;
for (CString cell = line.Tokenize(_T(" "), cpos); cpos > 0; cell = line.Tokenize(_T(" "), cpos))
{
int num;
num = _wtoi(cell);
arr[i][j] = num;
j++;
}
i++;
}
When I try to make arr a 2d vector, I stumbled upon "out of range" error. So, that means I have to somehow tokenize my text and put it in array. I haven't figured out how.
I have a function that takes in an array and defines a new array made up of a subset of the original array.
#include<iostream>
#include<cmath>
using namespace std;
double * subarray(double *array){
double *sub= new double[100];
for (int i=0; i<10; i++){
sub[i]=array[i];
}
return sub;
}
int main(){
double *x=new double[100];
double *y=new double[10];
for(int j=0; j<100; j++){
x[j]=sin(j*3.14/2.0);
}
y=subarray(x);
for(int k=0; k<10; k++){
cout<<y[k]<<endl;
}
return 0;
}
When I run this code some of the elements of the sub array come out as nan.
calling subarray is creating a new double[100] then passing that back out. But it's a completely separate array to y = new double[10]. Whenever you call "new" it's making a new thing, separate to all other "new" things. y gets the address of the "new double[100]" but it loses track of the address of the "new double[10]" you made in main, which is a memory leak. If you're going to return a pointer to an new'ly allocated item, start the pointer that's going to store it as a nullptr, and call "delete" or "delete []" when you're done, depending on whether it was a "new[]" thing or just "new".
#include<iostream>
#include<cmath>
using namespace std;
double * subarray(double *array) {
double *sub = new double[10]; // don't allocated more than you want to use
for (int i = 0; i < 10; i++) {
sub[i] = array[i];
}
return sub;
}
int main() {
double *x = new double[100];
double *y = nullptr; // don't set this if you're going to overwrite it
for (int j = 0; j < 100; j++) {
x[j] = sin(j*3.14 / 2.0);
}
y = subarray(x);
for (int k = 0; k < 10; k++) {
cout << y[k] << endl;
}
delete [] x; // if you make new things, delete them afterwards
delete [] y;
std::cin.get();
return 0;
}
I don't get any NaNs when I run this, but you are allocating a lot of memory that never gets set, inside the function. You're allocating 100 spaces but only writing to 10. This isn't necessarily an error, but it's not efficient.
I'm trying to fill an array with numbers 1111 to 8888, with each integer in the number being between 1 and 8 in c++. However, when I run it, it's only outputting large negative numbers indicating an error. I honestly have clue what the error is so it would be appreciated if you could help me out. Thanks!
int fillArray()
{
int arrayPosition;
int guesses[4096];
arrayPosition = 0;
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses[arrayPosition] = ((i * 1000) + (j * 100) + (k *10) + m);
cout << guesses[arrayPosition];
arrayPosition++;
}
return guesses[4096];
}
Your return type is wrong. int fillArray(), but you're trying to return an int[4096] that was declared on the stack... What you're actually doing with return guesses[4096]; is returning the first memory location after your array in memory, which is probably just garbage, hence your issue with large negative numbers.
You can fix it by allocating your array in the heap, and returning a pointer to the start of that array:
int * fillArray()
{
int arrayPosition;
int * guesses = new int[4096];
// other stuff stays the same...
return guesses;
}
However, since your function is called fillArray, it would make more sense to pass in an array and fill it rather than creating the array in the function. (If you wanted to do that, might call it something like make_1_to_8_array instead, to make it more clear that you're constructing something that will need to be deleted later.) Giving an int* as the first argument would allow you to pass in the base address of your array that you want filled:
void fillArray(int * guesses)
{
int arrayPosition;
// other stuff stays the same...
}
Or, if you want to verify that the you're using an array of the exact size:
void fillArray(int (&guesses)[4096])
{
int arrayPosition;
// other stuff stays the same...
}
Note that the function now returns void since you just update the array that was passed in, and you don't need to return anything new.
Your for-loops look correct, but your array handling is off, as is highlighted by other answers.
It is more usual in C++ to use std::vector and to pass this in by reference as an argument. This saves you having to handle memory allocations and deallocations. Here's an example, including the output in the for-loops:
#include <iostream>
#include <vector>
int fillArray(std::vector<int>& guesses)
{
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses.push_back((i * 1000) + (j * 100) + (k * 10) + m);
std::cout << guesses.back() << std::endl;
}
return guesses.back();
}
int main()
{
std::vector<int> guesses;
std::cout << fillArray(guesses) << std::endl;
}
You are creating your array locally then attempting to return it. If you try printing (to debug) out the result of your array prior to returning, you will see it is ok. However, once you return, the array is no linger valid. Try passing in an array into your function instead.