C++ New/Delete Error? - c++

I'm currently implementing a prime number sieve in C++ and I designed the code such that I should be able to control the size of the sieve (via an integer literal in the main function), but I am getting some odd errors all throughout. I haven't used C++ in a few years, but I remember using new and delete operators to manage heap memory.
My problem is sort of as follows...
The program works for some sieve sizes, but not others, and the effect is not strictly linear. For example, if I make the sieve of size 10,000, the program runs fine, but if I make it of size 1,000, the program crashes with a rather cryptic (for my amount of experience) message that always leads me to pages about C malloc assertion errors (via google). Additionally, the program works fine for 10,000 with delete statements peppered in, BUT will crash if I run in through valgrind with another useless (to me) message. As a result, I can't even debug the damn thing on my own DX
Any words of wisdom?
In particular, why would the program crash from a smaller input? In theory, this would be less likely to cause heap errors, would it not? Furthermore, why would valgrind be unable to run the program while it can go fine on its own? I suspect that (again) this has something to do with faulty or ugly use of the new/delete operators, but I am not totally certain. The part (about valgrind) that is particularly baffling to me is that it mentions in the error that I use the new operator on an unsigned long, which -as far as I can tell -is not what I do (at least not specifically). I assume this is some compiler related detail which I am not familiar with, but again I am not totally certain.
Code (with delete statement; works with size 10,000, but not through valgrind):
using namespace std;
#include <iostream>
#include <cstdlib>
#include <map>
#include <string>
long count_primes(bool* sieve,int size)
{
long count = 0;
for (int a=0;a<size;a++)
{
if (sieve[a])
{
count++;
}
}
return count;
}
int next_prime(bool* primes_so_far,int current_prime,int size)
{
for (int a=current_prime+1;a<size;a++)
{
if (primes_so_far[a]) return a;
}
return -2;
}
int prime_number_sieve(int* primes,int size)
{
if (size<4) return -2;
bool* sieve = new bool[size];
for (int a=0;a<size;a++)
sieve[a] = true;
sieve[0] = false;
sieve[1] = false;
int a=2;
do
{
int b = a;
if (b*a < size) sieve[b*a] = false;
do
{
b++;
sieve[b*a] = false;
} while (b*a < size);
a = next_prime(sieve,a,size);
} while (a*a < size);
long prime_list_size = (long) count_primes(sieve,size);
int* prime_list = new int[prime_list_size];
for (int b=0,c=0;b<size;b++)
{
if (sieve[b]) prime_list[c++] = b;
}
srand(time(NULL));
int rand_int1 = rand();
int rand_int2 = rand();
long rand_num1 = (((long) rand_int1) * prime_list_size)/RAND_MAX;
long rand_num2 = (((long) rand_int2) * prime_list_size)/RAND_MAX;
primes[0] = prime_list[rand_num1];
primes[1] = prime_list[rand_num2];
delete[] sieve;
delete[] prime_list;
return 0;
}
int main()
{
int* prime = new int[2];
prime_number_sieve(prime,10000);
cout << "\n";
cout << prime[0];
cout << "\n";
cout << prime[1];
cout << "\n";
return 0;
}
valgrind error for above:
==23738== Invalid write of size 1
==23738== at 0x400A4B: prime_number_sieve(int*, int) (in /home/botch/Downloads/unsorted/bre_final/a.out)
==23738== by 0x400C31: main (in /home/botch/Downloads/unsorted/bre_final/a.out)
==23738== Address 0x5ab83e0 is 0 bytes after a block of size 10,000 alloc'd
==23738== at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23738== by 0x4009CD: prime_number_sieve(int*, int) (in /home/botch/Downloads/unsorted/bre_final/a.out)
==23738== by 0x400C31: main (in /home/botch/Downloads/unsorted/bre_final/a.out)
==23738==
valgrind: m_mallocfree.c:303 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 4063233, hi = 0.
This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata. If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away. Please try that before reporting this as a bug.
Error for changing size to 1,000:
a.out: malloc.c:2392: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Aborted (core dumped)
EDIT:
I'm super grateful for all the (actual) help! Thanks to the answers below, the program will now run for most inputs (not too large, of course) but I am still getting the Valgrind error. I don't really mind that much, but I am curious to understand what is happening. I tried the suggestion below to change my selection mechanism of the random prime to (((long) rand_int1) % prime_list_size); rather than (((long) rand_int1) * prime_list_size)/RAND_MAX, but I had no noticeable results on the Valgrind side of things. I still cannot tell exactly where the invalid heap write is coming from. I will modify the code to see if it is my deletions that are causing and will report back.

The loop
do
{
b++;
sieve[b*a] = false;
} while (b*a < size);
does the assignment to sieve[b*a] BEFORE checking if b*a < size. This allows assignment of an element past the end of the array. That is undefined behaviour on the last iteration of this loop.
You would be better off using std::vector<bool> [noting it has some limitations that other vectors don't have] or std::bitset, rather than messing around manually with operators new and delete. Bear in mind it is still necessary to ensure your code doesn't fall off the end of standard containers.

I could see two problems in your code.
The first one is here:
do
{
b++;
sieve[b*a] = false;
} while (b*a < size);
This cannot prevent writing beyond the limit size, because the checking happens after the assignment `sieve[b*a] = false;
while (b*a < size)
{
sieve[b*a] = false;
b++;
}
The other problem I see is here:
long rand_num1 = (((long) rand_int1) * prime_list_size)/RAND_MAX;
long rand_num2 = (((long) rand_int2) * prime_list_size)/RAND_MAX;
The term in the multiplication could lead to overflow. I guess you want to get a random index less than size? You could simply do it this way:
long rand_num1 = (((long) rand_int1) % prime_list_size);
long rand_num2 = (((long) rand_int2) % prime_list_size);
Sure this will not yield a perfect uniform distribution, but it will work. For a better distribution take a look to the number random generators of the std library, and its vector as well, which is a very good tool for what you are doing.

Related

Valgrind - invalid read and write

I have a mystery that I do not have an answer for. I have written a simple program in C++(and I should say that I'm not a professional C++ developer). Here it is:
#include <iostream>
int main(){
const int SIZE = 1000;
int pool1 [SIZE];
int pool2 [SIZE];
int result [SIZE*SIZE];
//Prepare data
for(int i = 0; i < SIZE; i++){
pool1[i] = i + 1;
pool2[i] = SIZE - i;
}
//Run test
for(int i = 0; i < SIZE; i++){
for(int j = 0; j < SIZE; j++){
result[i*SIZE + j] = pool1[i]*pool2[j];
}
}
return 0;
}
The program seems to work (I use it as a kind of benchmark for different languages) but then I ran it with valgrind and it started complaing:
==25912== Invalid read of size 4
==25912== at 0x804864B: main (in /home/renra/Dev/Benchmarks/array_iteration/array_iteration_cpp)
==25912== Address 0xbee79da0 is on thread 1's stack
==25912== Invalid write of size 4
==25912== at 0x8048632: main (in /home/renra/Dev/Benchmarks/array_iteration/array_iteration_cpp)
==25912== Address 0xbeaa9498 is on thread 1's stack
==25912== More than 10000000 total errors detected. I'm not reporting any more.
==25912== Final error counts will be inaccurate. Go fix your program!
Hmm, does not look good. Size 4 probably refers to the size of int. As you can see at first I was using SIZE 1000 so the results array would be 1,000,000 ints long. So, I thought, it was just overflowing and I needed a larger value type(at least for the iterators and the array of results). I used unsigned long long (the max of unsigned long is 18,446,744,073,709,551,615 and all I needed was 1,000,000 - SIZE*SIZE ). But I'm still getting these error messages (and they still say the read and write size is 4 even though sizeof(long long) is 8).
Also the messages are not there when I use a lower SIZE, but they seem to kick in exactly at SIZE 707 regardless of the used type. Anybody has a clue? I'm quite curious :-).
C and C++ both have no clear limit on what sizes of arrays you will be able to use on the stack and also usually no builtin protection. Just don't allocate such large chunks as automatic (scope local) variables. Use malloc in C or new in C++ for such a purpose.

std::bad_alloc without going into swap space

I'm trying to understand why I am getting std::bad_alloc exceptions when I seem to have enough (virtual?) memory available to me.
Essentially I have a prime number generator (Eratosthenes sieve (not segmented yet)) where I'm newing bools for an indicator array, and then newing ints for the primes I've found under a bound I specify on the command line.
I have 1GB RAM (some of this will be hogged by my OS (ubuntu 10.04), and probably some of it is not available as heap memory (am I wrong here?)) and 2.8 GB of swap space (I believe that was auto set for me when installing Ubuntu)
If I set an upper bound of 600000000 then I'm asking for 0.6 GB of memory for my indicator array and roughly 30000000*4 bytes (slight over estimate given there are 26355867 primes less than 500000000) for my primes array, and a few variables here and there; this means I'm asking for about .72 (+ negligible) GB of memory which I believe should be covered by the swap space available to me (I am aware touching that stuff will slow my program down ridiculously). However I am getting std::bad_allocs.
Could anyone point out what I'm missing here? (one last thing having changed long long ints to ints before pasting my last error was a seg fault (my numbers are way below 2^31 though so I can't see where I'm overflowing) - still trying to figure that one out)
My code is as follows (and without taking away from me the benefit of my own investigation into quicker algorithms etc.. I'd be appreciative of any code improvements here! (i.e. if I'm committing major no-no s))
main.cpp
#include <iostream>
#include <cmath>
#include "Prime.hpp"
#include <ctime>
#include <stdio.h>
#include <cstring>
//USAGE: execute program with the nth prime you want and an upper bound for finding primes --too high may cause bad alloc
int main(int argc, const char *argv[])
{
int a = strlen(argv[1]);
clock_t start = clock();
if(argc != 2)
{
std::cout << "USAGE: Enter a positive inputNumber <= 500000000.\n"
<< "This inputNumber is an upper bound for the primes that can be found\n";
return -1;
}
const char* primeBound = argv[1];
int inputNum = 0;
for(int i = 0; i < strlen(argv[1]); i++)
{
if(primeBound[i] < 48 || primeBound[i] > 57 || primeBound[0] == 48)
{
std::cout << "USAGE: Enter a positive inputNumber <= 500000000.\n"
<< "This inputNumber is an upper bound for the primes that can be found\n";
return -1;
}
inputNum = (int)(primeBound[i]-48) + (10 * inputNum);
}
if(inputNum > 600000000)//getting close to the memory limit for this machine (1GB - memory used by the OS):
//(each bool takes 1 byte and I'd be asking for more than 500 million of these
//and I'd also asking for over 100000000 bytes to store the primes > 0.6 GB)
{
std::cout << "USAGE: Enter a positive inputNumber <= 500000000.\n"
<< "This inputNumber is an upper bound for the primes that can be found\n";
return -1;
}
Prime p(inputNum);
std::cout << "the largest prime less than " << inputNum << " is: " << p.getPrime(p.getNoOfPrimes()) << "\n";
std::cout << "Number of primes: " << p.getNoOfPrimes() << "\n";
std::cout << ((double)clock() - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
Prime.hpp
#ifndef PRIME_HPP
#define PRIME_HPP
#include <iostream>
#include <cmath>
class Prime
{
int lastStorageSize;
bool* primeIndicators;
int* primes;
int noOfPrimes;
void allocateIndicatorArray(int num);
void allocatePrimesArray();
void generateIndicators();
void generatePrimeList();
Prime(){}; //forcing constructor with param = size
public:
Prime(int num);
int getNoOfPrimes();
int getPrime(int nthPrime);
~Prime(){delete [] primeIndicators; delete [] primes;}
};
#endif
Prime.cpp
#include "Prime.hpp"
#include <iostream>
//don't know how much memory I will need so allocate on the heap
void Prime::allocateIndicatorArray(int num)
{
try
{
primeIndicators = new bool[num];
}
catch(std::bad_alloc ba)
{
std::cout << "not enough memory :[";
//if I'm looking for a particular prime I might have over-allocated here anyway...might be worth
//decreasing num and trying again - if this is possible!
}
lastStorageSize = num;
}
void Prime::allocatePrimesArray()
{
//could probably speed up generateIndicators() if, using some prime number theory, I slightly over allocate here
//since that would cut down the operations dramatically (a small procedure done many times made smaller)
try
{
primes = new int[lastStorageSize];
}
catch(std::bad_alloc ba)
{
std::cout << "not enough memory :[";
//if I'm looking for a particular prime I might have over-allocated here anyway...might be worth
//decreasing num and trying again - if this is possible!
}
}
void Prime::generateIndicators()
{
//first identify the primes -- if we see a 0 then start flipping all elements that are multiples of i starting from i*i (these will not be prime)
int numPrimes = lastStorageSize - 2; //we'll be starting at i = 2 (so numPrimes is at least 2 less than lastStorageSize)
for(int i=4; i < lastStorageSize; i+=2)
{
primeIndicators[i]++; //dispense with all the even numbers (barring 2 - that one's prime)
numPrimes--;
}
//TODO here I'm multiple counting the same things...not cool >;[
//may cost too much to avoid this wastage unfortunately
for(int i=3; i < sqrt(double(lastStorageSize)); i+=2) //we start j at i*i hence the square root
{
if(primeIndicators[i] == 0)
{
for(int j = i*i; j < lastStorageSize; j = j+(2*i)) //note: i is prime, and we'll have already sieved any j < i*i
{
if(primeIndicators[j] == 0)
{
numPrimes--;//we are not checking each element uniquely yet :/
primeIndicators[j]=1;
}
}
}
}
noOfPrimes = numPrimes;
}
void Prime::generatePrimeList()
{
//now we go and get the primes, i.e. wherever we see zero in primeIndicators[] then populate primes with the value of i
int primesCount = 0;
for(int i=2;i<lastStorageSize; i++)
{
if(primeIndicators[i] == 0)
{
if(i%1000000 = 0)
std::cout << i << " ";
primes[primesCount]=i;
primesCount++;
}
}
}
Prime::Prime(int num)
{
noOfPrimes = 0;
allocateIndicatorArray(num);
generateIndicators();
allocatePrimesArray();
generatePrimeList();
}
int Prime::getPrime(int nthPrime)
{
if(nthPrime < lastStorageSize)
{
return primes[nthPrime-1];
}
else
{
std::cout << "insufficient primes found\n";
return -1;
}
}
int Prime::getNoOfPrimes()
{
return noOfPrimes;
}
Whilst I'm reading around has anybody got any insight on this?
edit For some reason I decided to start newing my primes list with lastStorageSize ints instead of noOfPrime! thanks to David Fischer for spotting that one!
I can now exceed 600000000 as an upper bound
The amount of memory you can use inside your program is limited by the lesser of the two: 1) the available virtual memory, 2) the available address space.
If you are compiling your program as a 32-bit executable on a platform with flat memory model, the absolute limit of addressable space for a single process is 4GB. In this situation it is completely irrelevant how much swap space you have available. You simply can't allocate more than 4GB in a flat-memory 32-bit program, even if you still have lots of free swap space. Moreover, a large chunk of those 4GB of available addresses will be reserved for system needs.
On such a 32-bit platform allocating a large amount of swap space does make sense, since it will let you run multiple processes at once. But it does nothing to overcome the 4GB address space barrier for each specific process.
Basically, think of it as a phone number availability problem: if some region uses 7-digit phone numbers, then once you run out of the available 7-digit phone numbers in that region, manufacturing more phones for that region no longer makes any sense - they won't be usable. By adding swap space you essentially "manufacturing phones". But you have already run out of available "phone numbers".
The same issue formally exists, of course, with flat-memory model 64-bit platforms. However, the address space of 64-bit platform is so huge, that it is no longer a bottleneck (you know, "64-bit should be enough for everyone" :) )
When you allocate the sieve,
void Prime::allocateIndicatorArray(int num)
{
try
{
primeIndicators = new bool[num];
}
catch(std::bad_alloc ba)
{
std::cout << "not enough memory :[";
}
lastStorageSize = num;
}
you set lastStorageSize to num, the given bound for the primes. Then you never change it, and
void Prime::allocatePrimesArray()
{
try
{
primes = new int[lastStorageSize];
}
catch(std::bad_alloc ba)
{
std::cout << "not enough memory :[";
}
}
try to allocate an int array of lastStorageSize elements.
If num is around 500 million, that's around 2 GB that you request. Depending on operating system/overcommitting strategy, that can easily cause a bad_alloc even though you only need a fraction of the space actually.
After the sieving is finished, you set noOfPrimes to the count of found primes - use that number to allocate the primes array.
Since the memory usage of the program is so easy to analyze, just let the memory layout be completely fixed. Don't dynamically allocate anything. Use std::bitset to get a fixed-size bitvector, and make that a global variable.
std::bitset< 600000000 > indicators; // 75 MB
This won't take up space on disk. The OS will just allocate pages of zeroes as you progress along the array. And it makes better use of each bit.
Of course, half the bits represent even numbers, despite there being only one even prime. Here are a couple prime generators that optimize out such things.
By the way, it's better to avoid explicitly writing new if possible, avoid calling functions from the constructor, and to rethrow the std::bad_alloc to avoid allowing the object to be constructed into an invalid state.
The first question is "what other processes are running?" The
2.87 GB of swap space is shared between all of the running
processes; it is not per process. And frankly, on a modern
system, 2.8 GB sounds fairly low to me. I wouldn't try to run
recent versions of Windows or Linux with less than 2GB ram and
4GB swap. (Recent versions of Linux, at least in the Ubuntu
distribution, especially, seem to start up a lot of daemons
which hog the memory.) You might want to try top, sorted on
virtual memory size, just to see how much other processes are
taking.
cat /proc/meminfo will also give you a lot of valuable
information about what is actually being used. (On my system,
running just a couple of xterm with bash, plus Firefox, I
have only 3623776 kB free, on a system with 8GB. Some of the
memory counted as used is probably things like disk caching,
which the system can scale back if an application requests
memory.)
Second, concerning your seg faults: by default, Linux doesn't
always report allways report allocation failures correctly; it
will often lie, telling you that you have the memory, when you
don't. Try cat /proc/sys/vm/overcommit_memory. If it
displays zero, then you need to change it. If this is the case,
try echo 2 > /proc/sys/vm/overcommit_memory (and do this in
one of the rc files). You may have to change the
/proc/sys/vm/overcommit_ratio as well to get reliable behavior
from sbrk (which both malloc and operator new depend on).

How can I allocate a massive boolean array that currently throws std::bad_alloc errors during allocation?

I've seen several questions related to this, but I want verification that I'm having a similar problem. My code allocates a boolean array with a very large number of elements. This is my code, compiling on an x86_64 Linux machine:
#include <iostream>
#include <math.h>
using std::cout;
using std::endl;
using std::nothrow;
long problem3()
{
long upper_bound = 600851475143;
long max_prime_factor = 1;
long max_possible_prime = (long) sqrt(upper_bound) + 1;
bool * primes;
primes = new (nothrow) bool[upper_bound];
primes[0] = false; //segmentation fault occurs here
primes[1] = false;
for (long i = 2; i < upper_bound; i++)
primes[i] = true;
for (long number = 2; number < max_possible_prime; number++)
{
if (primes[number] == true)
{
if (upper_bound % number == 0)
{
max_prime_factor = number;
}
for (long j = number + number; j < upper_bound; j += number)
primes[j] = false;
}
else { continue; }
}
return max_prime_factor;
}
int main ( int argc, char *argv[] )
{
cout<<"Problem 3: "<<problem3()<<endl;
}
Building this code and running it as is gives a segmentation fault on this line:
primes[0] = false
If I remove the nothrow instruction to change this line:
primes = new (nothrow) bool[upper_bound];
to this:
primes = new bool[upper_bound];
I get an error message stating:
terminate called after throwing an instance of 'std::bad_alloc'
I think this means that the allocation is failing, presumably because of the size (based on similar questions and other referenced links.
The debugger in CodeBlocks shows that primes remains set to 0x0 even after its supposed to be allocated. Valgrind confirms this:
==15436== Command: ./main
==15436==
==15436== Invalid write of size 1
==15436== at 0x400A81: problem3() (main.cpp:54)
==15436== by 0x400B59: main (main.cpp:77)
==15436== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==15436==
==15436==
==15436== Process terminating with default action of signal 11 (SIGSEGV)
==15436== Access not within mapped region at address 0x0
==15436== at 0x400A81: problem3() (main.cpp:54)
==15436== by 0x400B59: main (main.cpp:77)
==15436== If you believe this happened as a result of a stack
==15436== overflow in your program's main thread (unlikely but
==15436== possible), you can try to increase the size of the
==15436== main thread stack using the --main-stacksize= flag.
==15436== The main thread stack size used in this run was 8388608.
==15436==
==15436== HEAP SUMMARY:
==15436== in use at exit: 0 bytes in 0 blocks
==15436== total heap usage: 1 allocs, 0 frees, 0 bytes allocated
==15436==
==15436== All heap blocks were freed -- no leaks are possible
==15436==
==15436== For counts of detected and suppressed errors, rerun with: -v
==15436== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 3 from 3)
Segmentation fault
Question: I know about std::vector, so should I use that to allocate this array? I'm open to trying a different algorithm as well, but I would like to know if there is a nuance of C++ I'm missing that will allow me to allocate such an array (even though it's absolutely massive and I understand that). I tried to debug this question as much as possible too, but if there is anything else I should have provided, let me know so I can use the tools the next time I run into trouble.
An extremely simple algorithm you can use to factorize the (large) number you're working with is Pollard's Rho Algorithm.
I will leave the mathematical explanation out for brevity's sake, but you can find the details on the Wikipedia article.
unisgned long long GCD(unisgned long long x, unisgned long long y)
{
while (y != 0)
{
unsigned long long t = b;
b = a % b;
a = t;
}
return a;
}
unsigned long long f(unsigned long long x, unsigned long long n)
{
return (x * x + 1) % n;
}
unsigned long long PollardRho(unsigned long long n)
{
unsigned long long x = 2, y = 2, d = 1;
while (d == 1)
{
x = f(x);
y = f(f(y));
d = GCD(std::abs(x - y), n);
}
if (d == n)
throw "Failure";
return d;
}
unsigned long long MaxFactor(unsigned long long n)
{
unsigned long long largest = 1;
while (n != 1)
{
unsigned long long factor = PollardRho(n);
largest = std::max(largest, factor);
n /= factor;
}
return largest;
}
Note: I didn't actually test the C++ code. I prototyped it in Mathematica and it correctly returned the maximal prime factor as being 6857.
Use std::vector<bool> or std::bitset which are specifically made for this purpose with data density and fast operations in mind. In an regular array of bools every single element is allocated at least a byte, instead of a bit.
Assuming that 600851475143 is a composite number, its largest prime factor is less than or equal to sqrt(600851475143) or about 775146. Your sieve doesn't need to be any larger than that.
This problem (Project Euler #3) can also be solved with simple brute-forced factorization. That method only takes about .002 seconds on my desktop PC.

C++ vector and memoization runtime error issues

I encountered a problem here at Codechef. I am trying to use a vector for memoization. As I am still new at programming and quite unfamiliar with STL containers, I have used vector, for the lookup table. (although, I was suggested that using map helps to solve the problem).
So, my question is how is the solution given below running into a run time error. In order to get the error, I used the boundary value for the problem (100000000) as the input. The error message displayed by my Netbeans IDE is RUN FAILED (exit value 1, total time: 4s) with input as 1000000000. Here is the code:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#define LCM 12
#define MAXSIZE 100000000
using namespace std;
/*
*
*/
vector<unsigned long> lookup(MAXSIZE,0);
int solve(int n)
{
if ( n < 12) {
return n;
}
else {
if (n < MAXSIZE) {
if (lookup[n] != 0) {
return lookup[n];
}
}
int temp = solve(n/2)+solve(n/3)+solve(n/4);
if (temp >= lookup[n] ) {
lookup[n] = temp;
}
return lookup[n];
}
}
int main(int argc, char** argv) {
int t;
cin>>t;
int n;
n = solve(t);
if ( t >= n) {
cout<<t<<endl;
}
else {
cout<<n<<endl;
}
return 0;
}
I doubt if this is a memory issue because he already said that the program actually runs and he inputs 100000000.
One things that I noticed, in the if condition you're doing a lookup[n] even if n == MAXSIZE (in this exact condition). Since C++ is uses 0-indexed vectors, then this would be 1 beyond the end of the vector.
if (n < MAXSIZE) {
...
}
...
if (temp >= lookup[n] ) {
lookup[n] = temp;
}
return lookup[n];
I can't guess what the algorithm is doing but I think the closing brace } of the first "if" should be lower down and you could return an error on this boundary condition.
You either don't have enough memory or don't have enough contiguous address space to store 100,000,000 unsigned longs.
This mostly is a memory issue. For a vector, you need contiguous memory allocation [so that it can keep up with its promise of constant time lookup]. In your case, with an 8 byte double, you are basically requesting your machine to give you around 762 mb of memory, in a single block.
I don't know which problem you're solving, but it looks like you're solving Bytelandian coins. For this, it is much better to use a map, because:
You will mostly not be storing the values for all 100000000 cases in a test case run. So, what you need is a way to allocate memory for only those values that you are actually memoize.
Even if you are, you have no need for a constant time lookup. Although it would speed up your program, std::map uses trees to give you logarithmic look up time. And it does away with the requirement of using up 762 mb contiguously. 762 mb is not a big deal, but expecting in a single block is.
So, the best thing to use in your situation is an std::map. In your case, actually just replacing std::vector<unsigned long> by std::map<int, unsigned long> would work as map also has [] operator access [for the most part, it should].

A "free(): invalid next size (fast)" in C++

I just ran into a free(): invalid next size (fast) problem while writing a C++ program. And I failed to figure out why this could happen unfortunately. The code is given below.
bool not_corrupt(struct packet *pkt, int size)
{
if (!size) return false;
bool result = true;
char *exp_checksum = (char*)malloc(size * sizeof(char));
char *rec_checksum = (char*)malloc(size * sizeof(char));
char *rec_data = (char*)malloc(size * sizeof(char));
//memcpy(rec_checksum, pkt->data+HEADER_SIZE+SEQ_SIZE+DATA_SIZE, size);
//memcpy(rec_data, pkt->data+HEADER_SIZE+SEQ_SIZE, size);
for (int i = 0; i < size; i++) {
rec_checksum[i] = pkt->data[HEADER_SIZE+SEQ_SIZE+DATA_SIZE+i];
rec_data[i] = pkt->data[HEADER_SIZE+SEQ_SIZE+i];
}
do_checksum(exp_checksum, rec_data, DATA_SIZE);
for (int i = 0; i < size; i++) {
if (exp_checksum[i] != rec_checksum[i]) {
result = false;
break;
}
}
free(exp_checksum);
free(rec_checksum);
free(rec_data);
return result;
}
The macros used are:
#define RDT_PKTSIZE 128
#define SEQ_SIZE 4
#define HEADER_SIZE 1
#define DATA_SIZE ((RDT_PKTSIZE - HEADER_SIZE - SEQ_SIZE) / 2)
The struct used is:
struct packet {
char data[RDT_PKTSIZE];
};
This piece of code doesn't go wrong every time. It would crash with the free(): invalid next size (fast) sometimes in the free(exp_checksum); part.
What's even worse is that sometimes what's in rec_checksum stuff is just not equal to what's in pkt->data[HEADER_SIZE+SEQ_SIZE+DATA_SIZE] stuff, which should be the same according to the watch expressions from my debugging tools. Both memcpy and for methods are used but this problem remains.
I don't quite understand why this would happen. I would be very thankful if anyone could explain this to me.
Edit:
Here's the do_checksum() method, which is very simple:
void do_checksum(char* checksum, char* data, int size)
{
for (int i = 0; i < size; i++)
{
checksum[i] = ~data[i];
}
}
Edit 2:
Thanks for all.
I switched other part of my code from the usage of STL queue to STL vector, the results turn to be cool then.
But still I didn't figure out why. I am sure that I would never pop an empty queue.
The error you report is indicative of heap corruption. These can be hard to track down and tools like valgrind can be extremely helpful. Heap corruptions are often hard to debug with a simple debugger because the runtime error often occurs long after the actual corruption.
That said, the most obvious potential cause of your heap corruption, given the code posted so far, is if DATA_SIZE is greater than size. If that occurs then do_checksum will write beyond the end of exp_checksum.
Three immediate suggestions:
Check for size <= 0 (instead of "!size")
Check for size >= DATA_SIZE
Check for malloc returning NULL
Have you tried Valgrind?
Also, make sure to never send more than RDT_PKTSIZE as size to not_corrupt()
bool not_corrupt(struct packet *pkt, int size)
{
if (!size) return false;
if (size > RDT_PKTSIZE) return false;
/* ... */
Valgrind is good ... but validating all your inputs and checking all error conditions is even better.
Stepping through the code in the debugger isn't a bad idea, either.
I would also call "do_checksum (size)" (your actual size), instead of DATA_SIZE (presumably "maximum size").
DATA_SIZE is a macro defined the max length in my program so the size
should be less than DATA_SIZE
even if that is true, your logic only creates enough memory to hold size characters.
so you should call
do_checksum(exp_checksum, rec_data, size);
and, if you do not want to use std::string (which is fine), you should switch from malloc/free to new/delete when talking C++