I have following code with one dynamically allocated array "data". I am passing array size as a command line argument. The program works fine until datasize = 33790. It gives segmentation fault if I try to provide a value > 33790.
"33790" might be machine specific. I am trying to understand why a dynamically allocated memory would return seg fault after a particular size. Any help is welcome. :)
#include "iostream"
#include <stdlib.h>
#include "iomanip"
#include "ctime"
#define N 100000
using namespace std;
int main(int argc, char* argv[])
{
int a;
cout<<"Size of int : "<<sizeof(int)<<endl;
long int datasize = strtol(argv[1],NULL,0);
cout<<"arg1 : "<<datasize<<endl;
double sum = 0;
int *data;
data = new int(datasize);
clock_t begin = clock();
for(int i = 0; i < N; i++) //repeat the inner loop N times
{
//fetch the data into the cache
//access it multiple times in order to amortize the compulsory miss latency
for (long int j = 0; j < datasize; j++)
{
sum += data[j]; //get entire array of data inside cache
}
}
clock_t end = clock();
double time_spent = (double) (end - begin);
cout<<"sum = "<<sum<<endl;
cout<<"Time Spent for data size = "<<argv[1]<<" is "<<time_spent<<endl;
delete[] data;
return 0;
}
You are not allocating any arrays (having multiple elements) but allocating only one int having value datasize.
Use new int[datasize] instead of new int(datasize) to allocate an array of int having datasize elements.
Related
I'm learning C++ and I'm wondering if anyone can explain some strange behaviour I'm seeing.
I'm currently learning memory management and have been playing around with the following code:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// pass back by pointer (old C++)
const int array_size = 1e6; // determines size of the random number array
vector<int> *RandomNumbers1()
{
vector<int> *random_numbers = new vector<int>[array_size]; // allocate memory on the heap...
for (int i = 0; i < array_size; i++)
{
int b = rand();
(*random_numbers).push_back(b); // ...and fill it with random numbers
}
return random_numbers; // return pointer to heap memory
}
int main (){
vector<int> *random_numbers = RandomNumbers1();
for (int i = 0; i < (*random_numbers).size(); i++){
cout << (*random_numbers)[i] + "\n";
}
delete random_numbers;
}
What I'm trying to do is get a pointer to a vector containing random integers by calling the RandomNumbers1() function, and then print each random number on a new line.
However, when I run the above code, instead of printing out a random number, I get all sorts of random information. It seems as though the code is accessing random places in memory and printing out the contents.
Now I know that I'm doing something stupid here - I have an int and I am adding the string "\n" to it. If I change the code in main() to the following, it works fine:
int main (){
vector<int> *random_numbers = RandomNumbers1();
for (int i = 0; i < (*random_numbers).size(); i++){
cout << to_string((*random_numbers)[i]) + "\n";
}
}
However I just can't understand the behaviour I'm getting with the "wrong" code - i.e. how adding the string "\n" to (*random_numbers)[i]
causes the program to access random areas of memory, instead of where my pointer is pointing to. Surely I have de-referenced the pointer and accessed the element at position i before "adding" "\n" to it? So how is the program instead accessing a totally different memory address?
"\n" is a string literal. It is an array and it is converted to a pointer pointing at its first element in your expression.
(*random_numbers)[i] is an integer.
Adding a pointer to an integer means that advance the pointer by the integer.
This will drive the pointer to out-of-range because "\n" has only 2 elements ('\n' and '\0') but the numbers returnd from the rand() function are likely to be larger than 2.
There are several issues with your code.
you are using delete instead of delete[] to free the array allocated with new[].
you are creating an array of 1000000 vectors, but populating only the 1st vector with 1000000 integers. You probably meant to create just 1 vector instead.
you can and should use the -> operator when accessing an object's members via a pointer. Using the * and . operators will also work, but is more verbose and harder to read/code for.
you are trying to print a "\n" after each number, but you are using the + operator when you should be using the << operator instead. You can't append a string literal to an integer (well, you can, but it will invoke pointer arithmetic and thus the result will not be what you want, as you have seen).
With that said, try something more like this:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int array_size = 1e6; // determines size of the random number array
vector<int>* RandomNumbers1()
{
vector<int> *random_numbers = new vector<int>;
random_numbers->reserve(array_size);
for (int i = 0; i < array_size; ++i)
{
int b = rand();
random_numbers->push_back(b);
}
return random_numbers;
}
int main (){
vector<int> *random_numbers = RandomNumbers1();
for (size_t i = 0; i < random_numbers->size(); ++i){
cout << (*random_numbers)[i] << "\n";
}
/* alternatively:
for (int number : *random_numbers){
cout << number << "\n";
}
*/
delete[] random_numbers;
}
However, if you are going to return a pointer to dynamic memory, you really should wrap it inside a smart pointer like std::unique_ptr or std::shared_ptr, and let it deal with the delete for you:
#include <iostream>
#include <vector>
#include <cmath>
#include <memory>
using namespace std;
const int array_size = 1e6; // determines size of the random number array
unique_ptr<vector<int>> RandomNumbers1()
{
auto random_numbers = make_unique<vector<int>>();
// or: unique_ptr<vector<int>> random_numbers(new vector<int>);
random_numbers->reserve(array_size);
for (int i = 0; i < array_size; ++i)
{
int b = rand();
random_numbers->push_back(b);
}
return random_numbers;
}
int main (){
auto random_numbers = RandomNumbers1();
for (size_t i = 0; i < random_numbers->size(); ++i){
cout << (*random_numbers)[i] << "\n";
}
/* alternatively:
for (int number : *random_numbers){
cout << number << "\n";
}
*/
}
Though, in this case, there is really no good reason to create the vector dynamically at all. 99% of the time, it is unnecessary and unwanted to use standard containers like that. Since the vector manages dynamic memory internally, there is no reason for the vector itself to also be created in dynamic memory. Return the vector by value instead, and let the compiler optimize the return for you.
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int array_size = 1e6; // determines size of the random number array
vector<int> RandomNumbers1()
{
vector<int> random_numbers;
random_numbers.reserve(array_size);
for (int i = 0; i < array_size; ++i)
{
int b = rand();
random_numbers.push_back(b);
}
return random_numbers;
}
int main (){
vector<int> random_numbers = RandomNumbers1();
for (size_t i = 0; i < random_numbers.size(); ++i){
cout << random_numbers[i] << "\n";
}
/* alternatively:
for (int number : random_numbers){
cout << number << "\n";
}
*/
}
I was trying to solve this question
but codechef.com says the answer is wrong.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int t, n, diff, mindiff;
cin >> t;
cin >> n;
int val[n];
while(t--)
{
mindiff = 1000000000;
for(int i = 0; i<n; i++)
{
cin >> val[i];
}
int a = 0;
for(a = 0; a<n ; a++)
{
for(int b=a+1; b<n ; b++)
{
diff = abs(val[a] - val[b]);
if(diff <= mindiff)
{
mindiff = diff;
}
}
}
cout << mindiff << endl;
}
return 0;
}
The results are as expected (for at least the tests I did) buts the website says its wrong.
There are a few things in your code that you should change:
Use std::vector<int> and not variable-length arrays (VLA's):
Reasons:
Variable length arrays are not standard C++. A std::vector is standard C++.
Variable length arrays may exhaust stack memory if the number of entries is large. A std::vector gets its memory from the heap, not the stack.
Variable length arrays suffer from the same problem as regular arrays -- going beyond the bounds of the array leads to undefined
behavior. A std::array has an at() function that can check boundary access when desired.
Use the maximum int to get the maximum integer value.
Instead of
mindif = 1000000000;
it should be:
#include <climits>
//...
int mindiff = std::numeric_limits<int>::max();
As to the solution you chose, the comments in the main section about the nested loop should be addressed.
Instead of a nested for loop, you should sort the data first. Thus finding the minimum value between two values is much easier and with less time complexity.
The program can look something like this (using the data provided at the link):
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
int main()
{
int n = 5;
std::vector<int> val = {4, 9, 1, 32, 13};
int mindiff = std::numeric_limits<int>::max();
std::sort(val.begin(), val.end());
for(int a = 0; a < n-1 ; a++)
mindiff = std::min(val[a+1] - val[a], mindiff);
std::cout << mindiff;
}
Output:
3
To do this you can use a simple for():
// you already have an array called "arr" which contains some numbers.
int biggestNumber = 0;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] > biggestNumber) {
biggestNumber = arr[i];
}
}
arr.size will get the array's length so that you can check every value from the position 0 to the last one which is arr.size() - 1 (because arrays are 0 based in c++).
Hope this helps.
So, i have some issues with i suspect a memory leak, in order to test i wrote this small code. By commenting the following line:
printf("Calc index: %d\n", ArrLength);
the code runs well. But when i uncomment it, the program crashed after a couple thousand threads.. When i use try/catch, the program just crashed inside the try function. Anyone who can help me out here?
#include "stdafx.h"
#include <process.h>
#include <iostream>
#include <mutex>
#include <windows.h>
using namespace std;
typedef struct {
int StartNode;
int EndNode;
int GangID;
int MemberID;
int ArrLength;
int arr[10000];
}t;
t *arg;
mutex m;
void myFunc(void *param) {
m.lock();
printf("Calculate thread started\n");
t *args = (t*)param;
int StartNode = args->StartNode;
int EndNode = args->EndNode;
int GangID = args->GangID;
int MemberID = args->MemberID;
int ArrLength = args->ArrLength;
printf("Calc index: %d\n", ArrLength);
free(args);
m.unlock();
}
int main()
{
for (int i = 0; i < 1000000; i++)
{
HANDLE handle;
arg = (t *)malloc(sizeof(t));
arg->StartNode = 2;
arg->EndNode = 1;
arg->GangID = 1;
arg->MemberID = 1;
arg->ArrLength = 5;
for (int j = 0; j < 10000; j++)
{
arg->arr[j] = j;
}
handle = (HANDLE)_beginthread(myFunc, 0, (void*)arg);
}
cin.get();
return 0;
}
Well, let do some calc. Your t struct has 40020 bytes per instance. You do allocate it 1M times that causes about 40 Gb allocated in total. And this is not all the memory required because each thread is not for free. By default, Windows allocates 1Mb stack per thread that gives you 1 Tb (one terabyte) of memory required just to let the threads live.
So, total memory amount is something like 1040 Gb. Do you really intend that?
I get an error under "int dArray[size]" saying that size needs to be a constant. Can someone explain what that means exactly?
I want it to be an array of size 4 and output 1, 3, 5, and 7.
#include <iostream>
using namespace std;
int *AllocateArray(int size, int value){
int dArray[size];
for (int i = 0; i <= size; i++){
dArray[i] = value;
value + 2;
}
}
int main(){
AllocateArray(4, 1);
}
Solved:
Here is the code that ended up working.
#include <iostream>
using namespace std;
int *AllocateArray(int size, int value){
int * Array = new int[size];
for (int i = 0; i < size; i++){
Array[i] = value;
value = value + 2;
}
for (int i = 0; i < size; i++){
cout << Array[i] << endl;
}
return Array;
}
int main(){
int *dArray = AllocateArray(4, 1);
}
In int dArray[size] size is not a constant value. Because of that you are getting that error. What you probably wanted to do was make a new array using a pointer and new like:
int * dArray = new int[size];
C++ requires that the size of arrays are determined at compile-time. As size is determined at runtime, the compiler complains.
If you are interested in having array-like behaviour with a size unknown at compile-time, then consider using std::vector.
The size of array should be a known constant in compile time, so that compiler can allocate correct memory for that array on the stack. Remember that such a declare is for stack variable. If you do want dynamic array, try std::vector.
You have to declare the size of an array using numbers, #define or const unsigned int. Otherwise they are considered variable length arrays.
Example:
const unsigned int MAX_ARRAY_SIZE = 14;
double my_array[MAX_ARRAY_SIZE];
I am getting a crash error at run time and not sure what exactly to do with the function or how to get the data for it.
FUNCTION DETAILS
Write a function that accepts an int array and size as arguments, then create a new array that is one element bigger than the given. Setting the first element to 0, then copying over what is in the argument array to the new array.
MAIN DETAILS
Use in a program reading int n from input, then read int n from file data name data
passing it to element shifter, then printing it to output (one per line).
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int element_shift(int elmts[], int size) {
int new_size = size + 1;
int shifter[new_size];
int *elmt_sft;
shifter[0] = 0;
for (int i = 1; i >= new_size; i++) {
shifter[i + 1] = elmts[i];
}
return *elmt_sft;
}
int main() {
fstream infile;
infile.open("D:\\data.txt");
int n, x;
infile >> x;
cout << "size of array: ";
cin >> n;
const int ARRAY_SIZE = n + x;
int elements[ARRAY_SIZE];
element_shift(elements, ARRAY_SIZE);
system("PAUSE");
return EXIT_SUCCESS;
}
First of all ARRAY_SIZE declared in the main function is not a constant variable but defined at run-time depending on user inputs. This means that the array elements should be created dynamically. On the other hand you read some x variable which is only used to define the size of the array and didn't initialized the array at all. I guess that the problem statement is to read the size of the array from the input, then the data of the array from the file.
There are also lot of mistakes in element_shift function.
Your code should look like something similar to this:
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
void element_shift(int* elmts, int size)
{
int new_size = size + 1;
int* shifter = new int[new_size];
shifter[0] = 0;
for(int i = 0; i < size; ++i)
{
shifter[i + 1] = elmts[i];
}
delete [] elmts;
elmts = shifter;
}
int main()
{
fstream infile;
infile.open("D:\\data.txt");
int n;
cout << "size of array: ";
cin >> n;
int* elements = new int[n];
for (int i = 0; i < n; ++i) {
infile >> elements[i];
}
element_shift(elements, n);
for (int i = 0; i < n; ++i) {
std::cout << elements[i] << std::endl;
}
return EXIT_SUCCESS;
}
First off, you spend alot of time creating the shifted array but don't return it back.
int element_shift(int elmts[], int size) {
int new_size = size + 1;
int shifter[new_size];
int *elmt_sft;
shifter[0] = 0;
for (int i = 1; i >= new_size; i++) {
shifter[i + 1] = elmts[i];
}
return *elmt_sft;
}
The elmt_sft pointer is never assigned. You are trying to access memory that is not there by using *elmt_sft. This may be causing your error. Also this function has no way of returning the new array shifter because that variable is locally declared and will disappear once the function exits. If you want to create something new in the function and still have it in memory once the function exits, I recommend creating the array dynamically and returning a pointer to it.
This is untested but should start you in the right direction. It will return a separate dynamically allocated array that will not override your other one.
int* element_shift(int elmts[], int size) {
int *result_array = new int[size + 1]; //dynamically create new array MAKE SURE TO DELETE
result_array[0] = 0; //set 0 index to 0
for (int i = 1; i < size + 1; i++)//start at 1 of the result and put value in
{
result_array[i] = elmts[i - 1];
}
return result_array; //returning pointer
}