I've written a program which computes the number of inversions in a .txt file (first number - amount of numbers, than go numbers themselves). On small input (5 or 10 numbers) it works fine, but when the input is 100,000 numbers (and each number less than 100,000) I get the following error:
incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug***
Here is the code:
#include <stdio.h>
long int merge(int *arr, const int start, const int half, const int end)
{
int s=start;
int i=0;
int cinv=0;
int j=half+1;
int* barr = new int[end+start-1];
while((s<=half)&&(j<=end)){
if(arr[s]<=arr[j]){
barr[i]=arr[s];
s++;
}
else{
barr[i]=arr[j];
j++;
cinv++;
}
i++;
}
if(s>half){
for(int k = j;k<=end;k++){
barr[i]=arr[k];
i++;
}
}
else{
for(int k=s;k<=half;k++){
barr[i]=arr[k];
i++;
}
}
for(int k=0;k<=end-start;k++) {
arr[k+start]=barr[k];
}
delete[] barr;
return cinv;
}
long int mergesort(int* arr, int start, int end){
int half=(start+end)/2;
long int cinv=0;
if (start<end){
cinv+=mergesort(arr, start, half);
cinv+=mergesort(arr, half+1, end);
cinv+=merge(arr, start, half, end);
return cinv;
}
return cinv;
}
int main(){
int len;
freopen("input.txt", "rt", stdin);
freopen("output.txt", "wt", stdout);
scanf("%d", &len);
int *arr= new int[len];
for (int i=0; i<len; i++){
scanf("%d", &arr[i]);
}
long int cinv=mergesort(arr, 0, len-1);
printf("\nInversions with merge=%ld", cinv);
delete [] arr;
return 0;
}
Thanks in advance for your help.
The dimension of your temporary array in merge,
int* barr = new int[end+start-1];
is not correct. When you call merge with start == 0 and end == 1, this will yield an array dimension of 0. At the other end of the array, it will allocate twice as much memory as needed. Change this to:
int* barr = new int[end - start + 1];
What allocating zero bytes does, is implementation-defined. Your program crashes reliably on my Linux platform even with small input arrays.
Related
I'm trying to create a function printarr that prints a dynamically sized array. However, whenever I try to run the code I get the error above. I tried copying code I found online as well, but get the same error, so I'm wondering if there's something wrong with my installation, or another part of the code is somehow affecting it. The entire thing seems super simple, which makes me even more stumped. Here's the code:
#include <iostream>
using namespace std;
//Generates an array with k inversions of size n
int* generate_k_inversion(int k, int n){
int *arr=new int(n);
//Check if number of inversions is possible
if(k>(n*(n-1)/2)){
cout<<"Impossible number of inversions!";
throw(-1);
}
//Loop to generate points
for(int i=0;i < n;i++){
arr[i]=i;
}
//Loop to invert
return arr;
}
//Copies dynamic arrays of size n
int* copy(int* arr1,int n){
int* arr2=new int(n);
for(int i=0;i<n;i++){
arr2[i]=arr1[i];
}
return(arr2);
}
//Generates output of best and worst cases of bubble and insertion sort in integers of size n
void test1(int n){
//generate best case
int *arrb1=generate_k_inversion(0,n);
int *arrb2=copy(arrb2,n);
delete [] arrb1;
delete [] arrb2;
//generate worst case
int *arrw1=generate_k_inversion((n*(n-1)/2),n);
int *arrw2=copy(arrw2,n);
delete [] arrw1;
delete [] arrw2;
}
//Prints a dynamic array arr of size n
void printarr(int* arr, int n)
{
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
}
//Just initialize both tests
int main(){
int size=10;
int* arr1=generate_k_inversion(0,size);
printarr(arr1,size);
delete [] arr1;
}
Thanks for the help
The line
int *arr=new int(n);
will allocate memory for a single int and initialize that int to n.
Therefore, the loop
for(int i=0;i < n;i++){
arr[i]=i;
}
will access arr out of bounds, causing undefined behavior.
What you probably want is to write
int *arr=new int[n];
instead, which will allocate memory for n values of type int.
I am gonna want maximum value from the array using a pointer. But I am not getting the accurate value. Please, help.
#include <iostream>
using namespace std;
int main()
{
int* largest;
int a[5]={4,5,666,7,8};
largest=a;
for(int i=1; i<5; i++)
{
if(*largest<*(largest+i))
{
*largest=*(largest+i);
largest=largest+i;
}
}
cout<<*largest;
}
I am getting 7339544 as an output rather than 666. I don't know what I am doing wrong.
You're indexing outside the array, causing undefined behaviour.
You're doing this
largest
|
v
| 4 | 5 | 666 | 7 | 8 |
^
|
largest + 1
then
largest
|
v
| 5 | 5 | 666 | 7 | 8 |
^
|
largest + 2
then
largest
|
v
| 5 | 7 | 666 | 7 | 8 | outside
^
|
largest + 3
(Note that you're also modifying the array, which you shouldn't.)
The main problem is that you're trying to use largest for three purposes simultaneously:
iterating,
storing the largest value,
storing the position of the largest value.
It should only point to the largest array element; you should only change its value, not the value of the element it points to.
int main()
{
const int a[5] = {4, 5, 666, 7, 8};
const int* largest = a;
for (int i = 1; i < 5; i++)
{
if (*largest < a[i])
{
largest = &a[i];
}
}
cout << *largest;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int generateNumber(int lower_limit, int upper_limit);
void fillArr(int *arr, unsigned int arrSize, int lower_limit, int upper_limit);
void printElementsArr(int *arr, unsigned int arrSize);
int maxElementArr(int *arr, unsigned int arrSize);
int main()
{
char expression;
int l_l, u_l;
int arrSize;
do{
srand(time(0));
printf("Insert array size:\n");
scanf("%d", &arrSize);
if(arrSize < 0){
while (arrSize<0){
printf("Insert positive array size:\n");
scanf("%d", &arrSize);
}
}
int array[arrSize];
printf("Insert lower limit of an array:\n");
scanf("%d", &l_l);
printf("Insert upper limit of an array:\n");
scanf("%d", &u_l);
while(u_l<l_l){
printf("the upper limit (%d) is smaller then the lower limit (%d), set a new upper limit of an array: ",u_l,l_l);
scanf("%d",&u_l);
}
fillArr(array, arrSize, l_l, u_l);
printElementsArr(array, arrSize);
maxElementArr(array, arrSize);
getchar();
printf("If you want to end the program insert 'n' else insert any key: ");
scanf("%c",&expression);
}while(expression != 'n');
}
//---------------------------------------------------------------------------------------------------------
int generateNumber(int lower_limit, int upper_limit){
return rand() % (upper_limit-lower_limit)+lower_limit;
}
void fillArr(int *arr, unsigned int arrSize, int lower_limit, int upper_limit){
int i = 0;
for (i; i < arrSize; i++){
*(arr+i)= generateNumber(lower_limit, upper_limit);
}
}
void printElementsArr(int *arr, unsigned int arrSize){
int i = 0;
printf("\n");
for (i; i < arrSize; i++){
printf("%d.element of an array: %d\n" ,i+1, *(arr+i));
}
}
int maxElementArr(int *arr, unsigned int arrSize){
int i = 1, max= *arr;
for(i; i<arrSize; i++){
if(max < *(arr+i)){
max = *(arr+i);
}
}
printf("\nThe max element of an array is: %d\n",max);
}
Because this code consists of multiple parts I created each independent functions for each problem a then I initially called them in my main function except the one that generates numbers. I used that one in the function where it fills the array with the numbers.
I created the function for generating a random numbers, filling an array with the numbers and printing every each element(number) of an array.
The reason I created the random number generator is because it is more dynamic than static array with pre-defined numbers and size of an array.
Also before the fill and print functions are called, first I ask the user for an array size and if the array size is lower than 0 therefore it will ask the user to insert a positive number and a I also ask user for a lower and an upper limit of an array and if the upper limit is lower than the lower limit a question with the information that the upper limit is lower than the upper one will pop-up over and over again with the option to insert a new upper limit unless the user inserts a number that is higher than the lower limit.
Also, the whole program is in loop with the question in the end if they want to end the program.
#include <iostream>
using namespace std;
int main()
{
int* largest;
int a[5]={4,5,666,7,8};
largest=a;
for(int i=1; i<5; i++)
{
if(*largest < a[i])
{
largest = &a[i];// This works perfectly
//largest = largest+i; There is no meaning of this line
}
}
cout<<*largest;
}
I have a function that merges two sorted arrays into one and returns a pointer to it. I want to use a for loop rather than a while. However in some test cases the last 1 or 2 elements of the merge array are not in their place. I would appreciate if someone can help solve this problem keeping the for loop.
int * mergeSort(int arr1[], int arr2[],int len)
{
/* len is the combined length of the two arrays */
static int sorted[100];
int pos1=0, pos2=0;
for (int i=0; i<len; i++)
{
if (arr1[pos1]<=arr2[pos2])
{
sorted[i]=arr1[pos1];
pos1++;
}
else
{
sorted[i]=arr2[pos2];
pos2++;
}
}
return sorted;
}
Your problem is that you don't seem to handle going past the end of the input arrays. If there is uninitialized memory - you get undefined behaviour.
You can avoid this by terminating your arrays with a sentinel value, for example INT_MAX, which should always be bigger than all possible values in the arrays:
int a[] = { 1, 2, 104, INT_MAX};
int b[] = { 101, 102, 105, INT_MAX};
int* ptr = mergeSort(a,b,6);
for(int i = 0; i < 6; i++){
cout << i << " " << ptr[i] << endl;
}
live demo
Or you can pass the actual lengths of both arrays and handle them correctly:
int * mergeSort(int arr1[], int len1, int arr2[],int len2)
{
/* len is the combined length of the two arrays */
static int sorted[100];
int pos1=0, pos2=0;
for (int i=0; i< len1 + len2; i++)
{
if ((pos2 == len2) || (arr1[pos1] <= arr2[pos2] && (pos1 < len1)))
{
sorted[i]=arr1[pos1];
pos1++;
}
else
{
sorted[i]=arr2[pos2];
pos2++;
}
}
return sorted;
}
live demo
This doesn't answer the question of what's wrong with your code, but to answer the question of how to merge two sorted ranges I would suggest std::merge:
int * mergeSort(int arr1[], int arr2[], int len1, int len2)
{
//I am not condoning the use of a static buffer here,
//I would probably use a std::vector or std::array,
//possibly a boost::static_vector if really necessary
static int sorted[100];
std::merge(arr1, arr1 + len1, arr2, arr2 + len2, sorted);
return sorted;
}
I also changed int len to int len1, int len2 because you need to know the lengths of the individual arrays, not just their combined length, to avoid reading past the end of the input arrays.
Question: Given a number k, find the sum of k positive big integers.
This is my code,it works, but our Online Judge is rejecting it, says segfault. Why does it show segfault? I could do it with two strings but why isn't this working?
#include <iostream>
#include <string.h>
using namespace std;
void add(int l,int k);
void append(char a[], int temp);
int o;
int tf=0;
int carry=0;
char b[1000000];
char a[10000][10000];
char c[1000000];
int main()
{
int k,x=0,l=0,m=0;
cin>>k;
while(x<k)
{
cin>>a[x];
if(strlen(a[x])>l)
{
l=strlen(a[x]);
}
x++;
}
x=0;
while(x<k)
{
if(strlen(a[x])<l)
{
int temp=0;
append(a[x],l-strlen(a[x]));
}
x++;
}
add(l,k);
if(carry!=0)
{
cout<<carry;
}
while(o>=0)
{
cout<<(int)b[o];
o--;
}
}
void add(int l,int k)
{
int lb=l-1;
int r=k-1;
int sum=0;
int x=0;
int neg=0;
while(lb>=0)
{
r=k-1;
sum=0;
while(r>=0)
{
sum=sum+a[r][lb]-48;
r--;
}
sum=sum+carry;
lb--;
if(sum>=10)
{
b[x]=sum%10;
carry=sum/10;
}
else
{
b[x]=sum;
carry=0;
}
sum=0;
o=x;
x++;
}
}
void append(char a[], int temp)
{
int l=0,m;
int tempb=temp;
m=strlen(a)-1;
while(temp>0)
{
c[l]='0';
l++;
temp--;
}
int z=0;
while(z<=m)
{
c[l]=a[z];
z++;
l++;
}
z=0;
while(z<=m+tempb)
{
a[z]=c[z];
z++;
}
}
Input Format:
First line contains k , which specifies the number of big numbers. Each of the next k lines contains a
big positive integer.
Output Format:
For each test case print the new big integer in a new line
Sample Input:
3
1331331
1313
453535322
Sample Output:
454867966
Constraints:
1<=k<=10
1<=number of digits in big numbers<=10000
Based on the problem statement:
Each input entry my have at most nmax = 10000 digits
Since each entry is stored as a C-style, zero-terminated string, each character array must have a length of (nmax + 1) = 10001 characters, to accomodate for the C-string terminator '\0'.
As you stored the entries into character arrays without leaving room for the zero terminator, assuming each entry was 10000-characters long:
Each entry with k>=1 overwrote the terminator or entry k-1, thus coalescing the entries together;
You thus ended with one giant string, with l = strlen(a[0]) = 100000;
From then on, all further processings were performed with these incorrect (coalesced) inputs and length, leading to buffer overrun at some point later in the execution.
I wrote a program for merge sort (i wrote the basic algorithm) - and it works fine. However, since I have to read the integers from a very large file I wanted to declare the array dynamically in the recursive calls . hence i wrote the following code , however it is giving me some errors, could you please help me identify where i am making the mistake?
The program is actually to count the number of inversions in an array ( if i < j and arr[i]>arr[j] , then this is an inversion). The program I have written is as below :
I dont want to declare a array of 10000 integers on stack everytime i go in recursive calls
The error i get is : std::bad_alloc at memory location 0x004dd940..
i have edited the question so it includes the error message. The execution breaks and visual studio goes into debug mode and opens a file osfinfo.c
#include<stdio.h>
#include <iostream>
using namespace std;
unsigned int mixAndCount(int * arr,int low, int mid,int high) {
int *num = new int[high-low+1];// THIS IS WHERE THE ERROR OCCURS
int l = low ;
int r = mid+1;
unsigned int count=0;
int i =low;
while((l<=mid)&&(r<=high))
{
if(arr[l]<=arr[r])
{
num[i]=arr[l];
l++;
}
else
{
num[i]=arr[r];
r++;
count=count + (mid-l+1);
}
i++;
}
if(l>mid)
{
for(int k=r;k<=high;k++)
{
num[i]=arr[k];
i++;
}
}
else
{
for(int k=l;k<=mid;k++)
{
num[i]=arr[k];
i++;
}
}
for(int k=low;k<=high;k++) arr[k]=num[k];
delete[] num;
return count;
}
unsigned int mergeAndCount(int * arr, int low , int high ) {
if(low>=high) {
return 0;
}
else {
int mid = (low+high)/2;
unsigned int left = mergeAndCount(arr, low , mid);
unsigned right = mergeAndCount(arr, mid+1, high);
unsigned int split = mixAndCount(arr, low , mid , high);
return left+right+split;
}
}
int main ()
{
int numArr[100000];
FILE * input = fopen("IntegerArray.txt", "r");
int i =0;
while(!feof(input)) {
int num;
fscanf(input, "%d", &num);
numArr[i] = num;
i++;
}
fclose(input);
unsigned int count = mergeAndCount(numArr,0, i-1 );
cout<<count<<endl;
return 0;
}
std::bad_alloc at memory location 0x004dd940..
Is an exception thrown by new when it cannot allocate requested memory successfully.
int *num = new int[high-low+1];
It seems the requested memory size is too large, which means you need to track values of high, low.
Be aware of dynamic memory allocation. Its really slower. Consider twice before you will leave your code in this form. You can make a simple testcase with std::chrono
http://en.cppreference.com/w/cpp/chrono/duration
you dont need dynamic allocation, everything is done in one local namespace.