トップページ⇒tech
455コメント137KB

new/deleteで異常終了する(Visual C++)

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2010/01/06(水) 20:35:52
大変、困っています。
Visual C++ 2008でコーディングしています。
コーディングは何度も何度も見直しました。
間違っていません。

なのに、実行するとnewで異常終了します。
debug版で動かすと動きます。release版で動かすと異常終了します。
デバッグのしようがありません。

ホントに、コーディングは正しいんです。
こういう症状の原因って何が考えられるでしょうか。

よろしくお願いします。

deleteでも異常終了します。
未初期化ポインタのdeleteとかそんなのではなくて、
本当にコーディングはあってるのに、異常終了します。

動きは、毎回違います。
例えば、printfデバッグをしようとしてprintfを
挿入すると、異常終了ポイントが変わります。
でも、newかdeleteで落ちます。

ホントに、ホントに、コーディングは合ってるのに
どうしようもありません。

もう何ヶ月も仕事が進みません。
このままだと、クビになっちゃいます。

お願いします、本当に、よろしくお願いします。
0002デフォルトの名無しさん2010/01/06(水) 20:43:53
それは大変だ!今すぐマイクロソフトのVisual C++ の開発責任者に電話しろ!
0003デフォルトの名無しさん2010/01/06(水) 20:55:46
コーディングを見直す前に
ローカルルールを見直せ
0004デフォルトの名無しさん2010/01/06(水) 21:08:29
┐(´ー`)┌ < サッサト クビニナレ
0005デフォルトの名無しさん2010/01/06(水) 21:18:13
このスレッドは天才チンパンジー「アイちゃん」が
言語訓練のために立てたものです。

アイと研究員とのやり取りに利用するスレッドなので、
関係者以外は書きこまないで下さい。

                  京都大学霊長類研究所
0006デフォルトの名無しさん2010/01/06(水) 21:23:08
>>1
これってdelete文を全部コメントアウトしても症状は同じ?
一再deleteしなくても一応は動くでしょ。deleteしないとメモリーオーバフローしちゃう?
0007デフォルトの名無しさん2010/01/06(水) 21:56:28
newで異常終了するってことは破壊されてる
0008デフォルトの名無しさん2010/01/06(水) 22:00:39
世界が?
0009デフォルトの名無しさん2010/01/06(水) 22:10:08
再インストールはしましたか??
0010デフォルトの名無しさん2010/01/06(水) 22:11:24
たぶん、間違ってないよ
0011デフォルトの名無しさん2010/01/06(水) 22:12:04
>>1
単発の質問でスレ立てはマナー違反な。
いちおう言っとくけど。
0012デフォルトの名無しさん2010/01/06(水) 22:12:54
2008ってリリースモードでもデバッグできない?
0013デフォルトの名無しさん2010/01/06(水) 22:13:09
ショートカットに Visuaru C++ って書いてないかチェックした方が良いな
001412010/01/06(水) 22:39:52
仕事のコードは載せられないですが、
下記のような感じなんです。

class C1 {
private:
// メンバ
int *a ; int *b ; C2 *c ; // C2はクラスね
public:
// コンストラクタ
C1( void ) { a = NULL ; b = NULL ; c = NULL ; return ; } ;
// デストラクタ
~C1( void ) { delete [] a ; delete [] b ; delete [] c ; return ; } ;
public:
// 初期化メソッド
int init( void ) {
a = new int[ 5 ] ; b = new int[ 5 ] ; c = new C2[ 5 ] ;
if ( !a || !b || !c ) {
delete [] a ; delete [] b ; delete [] c ;
a = NULL ; b = NULL ; c = NULL ;
return -1 ;
}
return 0 ;
} ;
public:
// 各種メソッド
int xxx( xxx ) { xxx ; } ;
} ;
001512010/01/06(水) 22:41:54
とにかく、
 い。 コンストラクタでNULLを入れる。
 ろ。 init()で領域確保。
 は。 失敗したらNULLを入れる。
 に。 deleteしたらNULLを入れる。
 ほ。 デストラクタで開放する。
は、徹底してます。

上記、C2の例みたく、デストラクタが
どんどん直列に呼び出される場合があります。
001612010/01/06(水) 22:43:06
> 6
いま、家なので、明日会社でやってみます。
もし仮にdeleteしないでうまくいったら、
deleteが原因ってことですか?

> 7
何が破壊されていますか。
破壊のよくある失敗原因はありますか。

> 11
ごめんなさい。しりませんでした。次から気をつけます。
でも、ネットで調べても全然のってないんです。
もう、2chにアクセスするエリートプログラマしか
頼れないんです。

> 12
えっ、そんな方法あるんですか。
明日会社でトライしてみます。
0017デフォルトの名無しさん2010/01/06(水) 22:44:37
>>14
んー、特に問題は見あたらないなー
0018デフォルトの名無しさん2010/01/06(水) 23:07:37
>>16
もし、deleteを外して直るなら、同じポインタを2回deleteしてる可能性があるね。
>>14 を見るかぎり大丈夫そうだけど。
まあ、簡単に外せるなら1回外してみるのが早いけどね。

関係ないと思うけど、// 初期化メソッド でa b cのどれかがNULLだったらa b c ともdeleteしてるけど
これおかしくない? NULLポインタをdeleteする事になちゃうよ。

if ( !a || !b || !c ) {
if( a ) delete [] a;
if( b ) delete [] b;
if( c ) delete [] c;
a = NULL; b = NULL; c = NULL;
return -1;
}

return 0;

にしないと。まあ、new が失敗するなんて殆んど考えられないけどね。
0019デフォルトの名無しさん2010/01/06(水) 23:13:18
NULLポインタはdeleteしても問題ないだろ。
0020デフォルトの名無しさん2010/01/06(水) 23:14:04
ま、C1型の値をコピーしちまってるオチだろうな。
0021デフォルトの名無しさん2010/01/06(水) 23:22:46
>>19
これはスマン。NULLポインタにdeleteしたことなんか無かったもんで。
0022デフォルトの名無しさん2010/01/06(水) 23:34:14
今日の魚影は濃いな
0023デフォルトの名無しさん2010/01/07(木) 00:13:19
そもそもnewが失敗した場合はNULLじゃなくて例外飛ぶから根本から間違えてんだけどな。

俺の感で言うと暗黙のoperator=でポインタをコピーして二重deleteとみた。
0024デフォルトの名無しさん2010/01/07(木) 00:14:28
> コーディングは何度も何度も見直しました。間違っていません。
ぼくわるくないもん! ぼくわるくないもん! ぼくわるくないもん! ぼくわるくないもん!
> なのに、実行するとnewで異常終了します。
わるいのはかんきょうだ! ぼくわるくないもん!

って時点でもうね。
ガチで書いているなら向いていないから辞めなさい。社会人を。
ネタで書いているなら向いていないから辞めなさい。人間を。
0025デフォルトの名無しさん2010/01/07(木) 00:17:12
しかし、何が悲しいって仕事でC++書いてるやつがこのレベルということ。
正直初心者がC++とかやると周りが不幸になるからやめたほうがいいよなー。

>>24
俺はC++で間違いなく書けたなんてRAII徹底しないと自信を持てないな。
生のポインタ使いつつ自信を持てる人をある意味、尊敬する。ある意味な。
0026デフォルトの名無しさん2010/01/07(木) 00:21:54
destructorに一個一個debug文を入れてどこでオチてるか
調べるのが定石
0027デフォルトの名無しさん2010/01/07(木) 00:40:55
>>23
一応、古い処理系だとnew失敗でnullが返る(std::nothrowなしでも)のはあるが…
自分はVS2008は使わんので分からないが、どっちなのだろうか?
>>25
烈しく同意。自分はC++に限らず「間違っていない」なんて口が割けても絶対に言えんわ。
0028デフォルトの名無しさん2010/01/07(木) 01:05:45
>>26
このパターンだと、多分それだと捕まらないんじゃないかなぁ。
> 動きは、毎回違います。
ってことだから。

アホの書いたコードがビルドやprintfデバッグで挙動が変わる場合、高確率でメモリ破壊やメモリ未初期化が原因。
それにより、バイナリが変わる度にヒープやスタック(やそこに残ったゴミ)の状況が変化し現象が変化する。
そしてほぼ全てのアホは、根拠皆無なのに何故か肥大化したプライドを守るために
目が曇って and/or 意図的に目を曇らせ、いくらコードを見てもそれを発見できずに自分以外の何かが原因だと喚く。

> このままだと、クビになっちゃいます。
それはヤバいね。先手を打って自分から退職願を出せば自分都合になるし退職金ももらえるよ?
0029デフォルトの名無しさん2010/01/07(木) 01:11:47
>>27
Visual C++ 6.0がNULLを返す最後の世代。

2008は9.0だから(数ヵ月後には2010(10.0)が出る)
普通のnewでNULLが帰ってくるのは現在考慮する必要は殆どないかと。

# 昔からのコードの保守で使わざるを得ない不幸な環境の人も多少はいるでしょうが
0030デフォルトの名無しさん2010/01/07(木) 01:40:16
しかもSTLは例外返すことを前提に作られてるから
メモリ無くなったらNULL参照で落ちるという糞処理系
まあ例外投げるようにすることはできるから
そうすりゃいいだけの話ではあるが
0031デフォルトの名無しさん2010/01/07(木) 02:48:05
operator=()とコピーコンストラクタをprivateに宣言して、
コンパイルが通るかどうか
0032デフォルトの名無しさん2010/01/07(木) 03:33:10
最善案
C++じゃなくC#或はJavaで書いてみる。
十分本質的なコードが出来た後にC++に移植する。
プログラムに課せられている問題と、C++特有の
技術上の問題がごっちゃになると難しい。(特に
VCは細かい技術上の配慮が必要で繊細)
(いきなりC++で完璧なコードを作ること自体に無
理がありそう。それなりにCやC#,Javaの経験があっ
たほうがいい)
C++コード書けるんだったらJava,C#の
コードを書くのはそれほど難しくは無い。
ただライブラリ関数の名前を覚えたり
調べたりするのがちょっと最初はきついかも
0033デフォルトの名無しさん2010/01/07(木) 04:04:28
どこが最善なのか。
0034デフォルトの名無しさん2010/01/07(木) 04:17:41
バグッたC/C++コードのデバッグだけはしないほうが
良い。精神衛生上問題が大有りだから。
仕様書がある限り、潔くそのコードを捨てて
書き直すのが最善。
JavaやC#とかのようなものでもそれが言える
C++だったら尚更。
0035デフォルトの名無しさん2010/01/07(木) 04:20:11
>>34
急がば回れ
でつねw
0036デフォルトの名無しさん2010/01/07(木) 05:06:19
プログラミング言語c++隅から隅まで読めば
>>14のコードじゃバグるのわかるだろ
0037デフォルトの名無しさん2010/01/07(木) 05:11:22
> ホントに、コーディングは正しいんです。
?
0038デフォルトの名無しさん2010/01/07(木) 05:20:48
Javaとかだったら
class c;
と
class[] c;
を混同しようものならコンパイルが通らないから
そういった系統のバグは発生しない点では初学者には優しいか...
0039デフォルトの名無しさん2010/01/07(木) 06:06:55
なるべく自分でメモリ管理しない
new C2[5] とかしないで std::vector<C2> を使う
添え字の範囲もチェックする
0040デフォルトの名無しさん2010/01/07(木) 07:31:38
クビになったらまた教えてね
0041デフォルトの名無しさん2010/01/07(木) 17:05:03
1は勤め先間違えたような感じが
0042デフォルトの名無しさん2010/01/07(木) 20:48:08
>>1 まず最初にするべきなのは、そげぶ
>ホントに、コーディングは正しいんです。
その幻想をぶち壊すこと。
0043デフォルトの名無しさん2010/01/07(木) 21:41:53
>>15そのコーディングスタイルは効果が薄い上に問題がある。

> い。 コンストラクタでNULLを入れる。
> ろ。 init()で領域確保。
まずコンストラクタとinitを分ける必要が無い。しかもinitを忘れないように徹底するのが難しい。
NULLがあるとNULLの場合の動作も対応する必要がありプログラムを安定させるのが難しくなる。

> は。 失敗したらNULLを入れる。
newで失敗すると例外が投げられるので意味が無い。

> に。 deleteしたらNULLを入れる。
> ほ。 デストラクタで開放する。
>は、徹底してます。
これらの徹底は難しいよ。参照とRAIIとスマポを使おう。ともかく生ポは扱わないのが近道。

追伸 目で見て確認は徹底とは言えないので注意
004412010/01/07(木) 21:55:51
>> 6, 18
ダメでした。deleteを一切しなくても、newで落ちます。

>> 12
やり方が良く分かりませんでしたが、異常終了ポイントや変数値の
チェックはできました。printfデバッグで異常終了するnewの直前まで
正しい値が出力される変数ですら、異常終了時にはめちゃめちゃに
破壊されてます。それどころか、プログラム全般にわたり変数の多くの
値がデタラメに改竄されてます。

>> 23, 27, 29
確かにそのようですね。勉強になりました。ただ、今回はそう簡単でも
ありません。例外をキャッチするコードを挿入しましたが、とにかく
newの途中で異常終了するので役に立ちません。

>> 24, 42
コーディングは合ってると書いたのは、単に質問だけすると、
ポインタの扱いとかdeleteの失敗とかそういう初心者向けの
コメントしか来ないだろうと思ったので、敢えて書きました。
コーディングとは別のところで良く陥るミスとかないですか。
例えば、コンパイラオプションを間違えてるとか。

>> 28
メモリ管理の問題の可能性が高いとは私も思っています。
ただ、newで落ちるというのが解せません。例え、メモリ
管理が間違っていて、誤った代入がされていたとしても、
newで落ちますか?どんな時に、newで異常終了しますか?
004512010/01/07(木) 22:02:19
話変わりますが、今日、情報処理の合格証書が届きました。
嬉しいんですが、このデバッグが終わらないと、心から喜べません。
よろしくお願いします。
0046デフォルトの名無しさん2010/01/07(木) 22:04:52
C2 クラスが怪しい
004772010/01/07(木) 22:10:22
俺の指摘が正しかったようだ
0048デフォルトの名無しさん2010/01/07(木) 22:31:29
>>38あたりが良いヒントかな
0049デフォルトの名無しさん2010/01/07(木) 22:44:45
>>44 そげぶ
>コーディングとは別のところで良く陥るミスとかないですか。
その幻想をぶち壊さないと前に進めないよ。

とりあえず、落ちる最小のコードをupしてごらん。
0050デフォルトの名無しさん2010/01/07(木) 22:55:18
deleteで例外吐くときってポインタがマイナス方向に走ってヒープ壊してる以外にないよね
■ このスレッドは過去ログ倉庫に格納されています