2

私はいくつかの奇妙なコードに取り組んでいますが、私にとっては良いコードではありません。

PIP_ADAPTER_INFO pAdapterInfo=(PIP_ADAPTER_INFO)new  
                               char[sizeof(IP_IP_ADAPTER_INFO)];

.
.
.
delete []pAdapterInfo;

ここで、 PIP_ADAPTER_INFO は構造体 IP_IP_ADAPTER_INFO へのポインタで、IP_IP_ADAPTER_INFO のサイズは 640 です。

delete []pAdapterInfo 呼び出しでクラッシュすることを予想していましたが、クラッシュはありませんでした。小さなテスト コードを書きました。

        class TestClass
        {

        public:
        /*  TestClass()
            {
            }
            ~TestClass()
            {
            }*/

        public:
            int array[10];
        };

        int main (int ac, char **av)

        {
            TestClass *myptr=(TestClass*) new char[10];
            delete []myptr;
            return 0;
        }

私が見るもの:

  1. c'tor と d'tor のコメントを外すと、テスト コードがクラッシュする (アサートが失敗する)
  2. コメントしたままにしておくと、何も失敗しません。

逆アセンブルが表示されていても、上記の両方のケースで異なります

/*****************************************************************/
/********Compiler provided c'tor and d'tor ***********************/
/*****************************************************************/
28:       TestClass *myptr=(TestClass*) new char[10];
00401268   push        0Ah
0040126A   call        operator new (004082d0)
0040126F   add         esp,4
00401272   mov         dword ptr [ebp-8],eax
00401275   mov         eax,dword ptr [ebp-8]
00401278   mov         dword ptr [ebp-4],eax
29:       delete []myptr;
0040127B   mov         ecx,dword ptr [ebp-4]
0040127E   mov         dword ptr [ebp-0Ch],ecx
00401281   mov         edx,dword ptr [ebp-0Ch]
00401284   push        edx
00401285   call        operator delete (004060d0)
0040128A   add         esp,4
30:
/*****************************************************************/
/********User provided c'tor and d'tor ***********************/
/*****************************************************************/
28:       TestClass *myptr=(TestClass*) new char[10];

28:       TestClass *myptr=(TestClass*) new char[10];
00401278   push        0Ah
0040127A   call        operator new (004083e0)
0040127F   add         esp,4
00401282   mov         dword ptr [ebp-8],eax
00401285   mov         eax,dword ptr [ebp-8]
00401288   mov         dword ptr [ebp-4],eax
29:       delete []myptr;
0040128B   mov         ecx,dword ptr [ebp-4]
0040128E   mov         dword ptr [ebp-10h],ecx
00401291   mov         edx,dword ptr [ebp-10h]
00401294   mov         dword ptr [ebp-0Ch],edx
00401297   cmp         dword ptr [ebp-0Ch],0
0040129B   je          main+4Ch (004012ac)
0040129D   push        3
0040129F   mov         ecx,dword ptr [ebp-0Ch]
004012A2   call        @ILT+0(TestClass::`vector deleting destructor') (00401005)
004012A7   mov         dword ptr [ebp-14h],eax
004012AA   jmp         main+53h (004012b3)
004012AC   mov         dword ptr [ebp-14h],0

C++ のこの機能を学ぶための専門知識を教えてください。

前もって感謝します。

4

2 に答える 2

12

IP_IP_ADAPTER_INFOここでは、 Windows のIP_ADAPTER_INFO構造を意味していると仮定しています。そうでない場合でも、これの要点は同じです。あなたのコードは未定義の動作につながっており、それを書いた人のせいです。すぐに修正してください。

charwithの配列を割り当てましたnewが、そのメモリを の配列であるかのように解放しますIP_ADAPTER_INFOcharC++ は、あなたが嘘をついていることを知らないので、あなたの配列を配列として扱おうとしますIP_ADAPTER_INFO

VC++は、ポインターの型を気にしない割り当てられたメモリに関する十分な情報を記録するため、これは時々機能しますが、これは悪であり、悪であり、悪であり、悪であり、違法なget-you-taken-out-back-and-shotコードです。delete[]

特定のコンパイラで動作する可能性がありますが、それは完全にまぐれです。代わりに次のことを行う必要があります。

PIP_ADAPTER_INFO pAdapterInfo = new IP_ADAPTER_INFO;
//DoSomethingToAdapterInfo(pAdapterInfo);
delete pAdapterInfo;

しかし、その場合でも、グローバル スコープでその構造を保持する必要があり、それ自体が設計の悪さを示している場合を除き、ここでnewandを使用するべきではありませんdelete。これに近いことをする必要があります:

IP_ADAPTER_INFO adapterInfo;
//DoSomethingToAdapterInfo(&adapterInfo);

C++ に (スタック上で) 割り当てと削除を処理させます。構造体を返す必要がある場合は、構造体へのポインターではなく構造体を返します (呼び出し元がメモリ管理について心配する必要がありません)。

スタック割り当ての代わりにヒープ割り当てを使用している理由が不明または固有の理由である場合は、そうすることが正当化される可能性がありますが、その場合でも、へのキャストnew char[...]PIP_ADAPTER_INFO良くありません。

于 2010-09-28T04:57:49.607 に答える
4

$5.3.5/3 - 「2 番目の選択肢 (配列の削除) では、削除するオブジェクトの動的型が静的型と異なる場合、動作は未定義です。73 )」

したがって、あなたが見ているのは、実際には未定義の動作です。

73) これは、void* 型のオブジェクトが存在しないため、void* 型のポインタを使用してオブジェクトを削除できないことを意味します。

于 2010-09-28T04:57:22.277 に答える