私はC++で素数の篩を現在実装していますが、私は篩のサイズを(主関数の整数リテラルを介して)制御することができるようにコードを設計しましたが、全体を通して。私は数年後にC++を使用しませんでしたが、ヒープメモリを管理するために演算子new
とdelete
を使用したことを覚えています。次のようにC++新規/削除エラー?
私の問題は、プログラムは、いくつかのふるいサイズではなく、他人のために働く、と効果が厳密に線形ではありません...一種の
です。例えば、私が10000のサイズのふるいを作っても、プログラムはうまく動作しますが、サイズを1000にすると、プログラムがクラッシュして(私の経験量では)、C mallocアサーションエラー(Google経由)。さらに、プログラムはのの削除文が入り込んだ状態で正常に動作しますが、valgrind
から別の役に立たない(私にとって)メッセージを実行するとクラッシュします。その結果、私は自分自身のDXで気になることをデバッグすることはできません
知恵の言葉?
特に、より小さいプログラムがクラッシュする理由は??理論的には、これはより少なく、ヒープエラーを引き起こす可能性が低いでしょうか?さらに、valgrind
はなぜそれ自体で問題なく動くことができないのですか?私は(再び)これは新しい/削除演算子の不完全または醜い使用と関係があると思うが、私は完全には確信していない。私にとって特に困惑している部分(約valgrind
)は、私がunsigned long
でnew
演算子を使用していることをエラーで言及しています。これは私がよく慣れていないコンパイラ関連の詳細ですが、やはり私は全く確信していません。
コード(DELETE文で、大き万ではなく、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
エラー:1,000にサイズを変更するための
==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.
がエラー:
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)
編集:
私はすべての(実際の)助けに非常に感謝しています!以下の答えのおかげで、プログラムはほとんどの入力に対して実行されるようになりました(でもも大きいですが)、私はまだValgrindエラーを受けています。私は本当に心配していませんその、しかし私は何が起こっているのか理解して奇妙です。私はランダムプライムの選択メカニズムを(((long) rand_int1) * prime_list_size)/RAND_MAX
ではなく(((long) rand_int1) % prime_list_size);
に変更するために以下の提案を試みましたが、Valgrind側では目立った結果はありませんでした。私はまだ無効なヒープ書き込みがどこから来ているのか正確には分かりません。コードを修正して、それが原因で削除されているかどうかを確認し、報告します。
このような問題を解決する適切なツールは、デバッガです。スタックオーバーフローを尋ねる前に、コードを一行ずつ進める必要があります。詳しいヘルプは、[小さなプログラムをデバッグする方法(Eric Lippert)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)を参照してください。最低でも、あなたはあなたが行った観察と一緒に、[編集]あなたの質問あなたの問題を再現[、最小完全、かつ検証](http://stackoverflow.com/help/mcve)の例を含むようにする必要があります\しますデバッガ。 –
私はdownvoteとリンクを感謝する限り、私は両方の*すべて*をカバーしていると思う。より具体的にするために質問を編集しました。しかし、助けてくれてありがとう。 – botch
valgrindには、メモリ違反エラー時にデバッガに侵入するオプションがあります。プログラムが破損したメモリを試みた時点でデバッガにダンプされます。このオプションを使用すると、バグの内容を正確に判断できるはずです。 –