Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

C++

C++で発生した「 _CrtIsValidHeapPointer(block)」と「is_block_type_valid(header->_block_use)」エラーについて

投稿日:2022年2月26日 更新日:

 

<目次>

(1) C++で発生した「 _CrtIsValidHeapPointer(block)」と「is_block_type_valid(header->_block_use)」エラーについて
 (1-1) 事象・発生状況
 (1-2) 原因
 (1-3) 対策
 (1-4) 参考

(1) C++で発生した「 _CrtIsValidHeapPointer(block)」と「is_block_type_valid(header->_block_use)」エラーについて

本記事ではC++で発生した「 _CrtIsValidHeapPointer(block)」と「is_block_type_valid(header->_block_use)」エラーについてご紹介します。

(1-1) 事象・発生状況

C++のプログラムを実行した結果、以下のエラーが発生しました。

●エラーメッセージ

Debug Assertion Failed!

Program:
XXXX
Line XXX

Expression: _CrtIsValidHeapPointer(block)

(図111)

Debug Assertion Failed!

Program:
XXXX
Line XXX

Expression: is_block_type_valid(header->_block_use)

(図112)

●事象発生のサンプルプログラム

 
上記のエラーを再現するためのサンプルプログラムをご紹介します。
#include <iostream>
using namespace std;
int main(void) {

    int n1 = 10;
    int* n1p = &n1;
    delete[] n1p;

}

目次にもどる

(1-2) 原因

下記の原因が考えられます。

●メッセージ「_CrtIsValidHeapPointer」の原因

・解放されるべきポインタが既に有効でない(or正しくない)場合

(発生例)「new」していないのに「delete[]」している場合
    int n1 = 10;
    int* n1p = &n1;
    delete[] n1p;

●メッセージ「is_block_type_valid(header->_block_use)」の原因

・こちらもメモリの使用や解放に関連しているケースが多く、例えば同じアドレスブロックを繰り返し削除した場合などに発生する様です。

(発生例)「new」していないのに「delete」している場合
    int n1 = 10;
    int* n1p = &n1;
    delete n1p;

目次にもどる

(1-3) 対策

上記の発生例の場合、対策としては「delete」対応する「new」の定義を設ける事で解決する事ができます。

(例)
    int* n1p = new int;
    n1p[0] = 10;
    delete n1p;
(図131)

なので、チェックする観点の例としては以下の通りです。
①「delete」しているのに「new」されていない箇所が無いかを確認する
②「new」に対しては「delete」で解放になっているかを確認する
③「new 型[N]」に対しては「delete[]」で解放になっているか確認する

目次にもどる

(1-4) 参考

●参考1

ちなみに、上記の②と③のケースはエラーではなく、下図のような警告になるようです。単一の非配列オブジェクトの場合は「new」と「delete」で、逆に配列オブジェクトの場合は「new []」と「delete[]」を使います。

・②がNGの例
⇒「new」に対して「delete[]」で解放している
 
・③がNGの例
⇒「new []」に対して「delete」で解放している

●参考2:②と③のNGで起きている事

「new[]」で返却されるポインタは常に割当てされたメモリの先頭を見るとは限りません。なぜなら、動的にメモリを割り当てる際は、その「サイズ」の情報を「先頭」に保持するため、その分だけオフセット(補正)されてしまい、先頭はサイズの情報となるためです。
 
int* n1p = new int[10];

 

例えば、下記のポインタ定義では要素を10つ確保していますが、このポインタのサイズ(要素10個)の情報を保持するため、先頭は1要素目のデータではなく、サイズになります。なので、ここで通常「delete[]」とすべき所を「delete」としてしまうと、そのオフセット分がミスマッチとなり警告に繋がっているようです。
 
 

Adsense審査用広告コード


Adsense審査用広告コード


-C++

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

C++の共用体とは?構造体との違いや使用方法について

  <目次> (1) C++の共用体とは?構造体との違いや使用方法について  (1-1) 共用体とは?構造体との違いは?  (1-2) 共用体の定義方法、変数定義方法、初期化方法  (1-3 …

Valgrindの使い方や見方について(基礎編)

  <目次> (1) Valgrindの使い方や見方について(基礎編)  (1-1) メモリリークのチェックのやり方  (1-2) 「valgrind」コマンドの基本的な使い方  (1-3) …

C++のunsigned char型とは?概要やsigned charとの違いもご紹介

<目次> (1) C++のunsigned char型とは?概要やsigned charとの違いもご紹介  (1-1) 概要  (1-2) サンプルプログラム①:疎通確認 (1) C++のunsign …

C++のfork関数の構文や使い方について

  <目次> (1) C++のfork関数の構文や使い方について  (1-1) fork()関数とは?概要や目的  (1-2) fork()関数の構文  (1-3) fork()関数のサンプ …

C++のtime関数とlocaltime関数の違いについて

  <目次> (1) C++のtime関数とlocaltime関数の違いについて  (1-1) C++のlocaltime関数の概要とサンプル  (1-2) C++のtime関数の概要とサン …

  • English (United States)
  • 日本語
Top