8064


表題の通りです。

バッファクラスを作ったのですが、newとreallocの混在に加えて、それをdeleteしています。このようにした場合に解放されない部分が発生したりしないかを確認したいと思っています。

[code]

    char *p = new char[10];
    p  = realloc((void*)p, 15);
    
    delete p[];
    
[/code]

よろしくお願いします。

すいませんdeleteはミスです。修正しました。


CC BY-SA 3.0
2015-03-18T09:33:04.053
8063
2015-03-18T14:02:30.657
2015-03-18T11:46:37.270
3496
3496
question
c++
C++でnewした後にrealloc()したポインタをdeleteしても問題ないですか？


`delete`してよいのは`new`で返されたポインタとNULLポインタのみです。  
それ以外のポインタを渡した場合の動作は未定義です。

774RRさんの指摘の通り、このコードだと`realloc`がなくても`new[]`に対して`delete`しているので動作は未定義です。

§ 3.7.4.2 Deallocation functions

> The value of the first argument supplied to a deallocation function may be a
> null pointer value; if so, and if the deallocation function is one supplied
> in the standard library, the call has no effect.  
>  Otherwise, the behavior is undefined if the value supplied to operator
> delete(void*) in the standard library is not one of the values returned by a
> previous invocation of either operator new(std::size_t) or operator
> new(std::size_t, const std::nothrow_t&) in the standard library, and the
> behavior is undefined if the value supplied to operator delete in the
> standard library is not one of the values returned by a previous invocation
> of either operator new or operator new[](std::size_t, const std::nothrow_t&)
> in the standard library.


CC BY-SA 3.0
2015-03-18T09:55:25.443
8064
2015-03-18T10:24:37.477
2015-03-18T10:24:37.477
3639
3639
8063
answer


残念ながら動作は保障されていません。正常に動作する環境も多いとは思いますが、環境間の差異や将来的なことを考えるととてもお勧めできません。  
`realloc`を使うなら、古き良き`malloc` / `free`を使用する必要があります。

もしくは、ご指摘の用途であれば、`std::vector`を使用することをおすすめします。

[code]

    #include <vector>
    int main() {
        std::vector<char> p(10);
    
        p[0] = 'a';
        p[1] = 'b';
        p[2] = '\0';
    
        p.resize(15); /* サイズを変更 */
        p[13] = 'x';
    
        return 0;
    }
    
[/code]


CC BY-SA 3.0
2015-03-18T09:56:37.103
8066
2015-03-18T09:56:37.103
6092
8063
answer


ダメです。 new [ ] が返してきたポインタを realloc に渡して動作する保証は無いです。  
ISO/IEC 14882:1998 18.4.1.1 operator new の 8  
malloc を呼ぶかどうかは未規定

18.4.1.2 operator new[] の 3  
operator new と同じ

ISO/IEC 9899:1999 7.20.3.4 realloc  
ptr が malloc (snip) によって返されたポインタと一致しないとき、未定義

そういう目的なら単純に std::vector で良いのではないかと。

delete も delete[] でなきゃだめぢゃん。


CC BY-SA 3.0
2015-03-18T10:03:29.353
8068
2015-03-18T10:03:29.353
8589
8063
answer


仕様についてのコメントがありますが、実際に問題も生じます。

new[]した際には各要素に対してそれぞれコンストラクターが実行されます。そしてdelete[]の際には各要素に対してそれぞれデストラクターが実行されます。さて
T* 変数にはアドレスしかなくdelete[]が何要素分のデストラクターを実行すればいいかが不明です。  
そのためコンパイラーはどこか別の領域に要素数を保持しておきdelete[]が呼ばれた際にはその情報を元にデストラクターを実行するようなコードを生成します。realloc()をしてしまうとこの情報が崩れます。

後出しで条件を追加されたので追記します。  
要素数をどこに保持しておくかですが、new[]の際にsize_tだけ大きく確保し、先頭に要素数を格納し、size_tだけずらしたアドレスを返す[over-
allocation](https://isocpp.org/wiki/faq/compiler-dependencies#num-elems-in-
new-array-
overalloc)という方法もあります。この場合、new[]で得られたアドレスそのものはmalloc()で返されたアドレスとは異なるためそもそもrealloc()に成功しません。この辺りは実装依存となり使用するのは危険です。


CC BY-SA 3.0
2015-03-18T13:15:08.317
8074
2015-03-18T14:02:30.657
2015-03-18T14:02:30.657
4236
4236
8063
answer


[Bjarne
StroustrupによるC++のスタイルとテクニックに関するFAQ](http://www.libjingu.jp/trans/bs_faq2-j.html#realloc)：

> **CスタイルとC++スタイルのメモリ割り当てと解放を同時に使用できますか**
>
> malloc()とnewを同じプログラムの中で使用できるという意味では、答えはイエス です。
>
> malloc()でオブジェクトを割り当てて、deleteで解放することはできないという
> 意味では、答えはノーです。newで割り当てて、free()で解放することも、newで割り
> 当てられた配列に対してrealloc()を使用することもできません。
>
> C++の演算子newとdeleteは、オブジェクトの適切な生成と解体を保証します。
> したがって、コンストラクタとデストラクタを起動する必要があるところでは、
> それを起動します。Cスタイルの関数、malloc()、calloc()、free()、realloc()は、
> それを保証しません。さらに、newとdeleteで使用されるメモリの取得と解放のメカ
> ニズムが、malloc()とfree()のものと互換性があるという保証はありません。
> 仮にこれらを混在させたスタイルが、あなたのシステムで動作したとしても、今の ところそれは単に「ラッキー」であったということです。
>
> もしrealloc()の必要性を感じるなら(そう感じる人は多い)、標準ライブラリ のvectorを使うことを検討してみてください。  
>  [...]


CC BY-SA 3.0
2015-03-18T13:37:01.063
8076
2015-03-18T13:37:01.063
49
8063
answer