• 【逆向】03-20扩大节 c++代码完成 ;类当作函数参数却调用了析构函数疑难分析


    若要看PE结构操作最新代码,点击主页查看!!

     

    和上一节的代码相比,本文章主要修复了上一篇文章代码中PE类中的Analyze函数,这样不管是Before_Stretch_Data还是Stretch_Data,Shrink_Data,在这个函数中都可以分析出PE结构

    另外新添加了函数Expand_Section函数,可以自动扩大最后一个节,并写入新的文件中,亲测可以使用,程序可以完美运行
    Expand_Section函数的思路就是
     

    扩大节:

    只能扩大最后一个节

    • 1.拉伸到内存

    • 2.分配一块新的空间,SizeOfImage + Ex(扩大出来的空间)

    • 3.将最后一个节的SizeOfRawData和VirtualSize改成N SizeOfRawData=VirtualSize=N N=(原来的SizeOfRawData和VirtualSize两者比较大的那一个内存对齐后的值)+Ex

    • 4.修改SizeOfImage大小 SizeOfImage=SizeOfImage+Ex

     

    期间我遇到一个百思不得其解的问题:
    就是我将一个类作为参数继续函数传值,但是程序运行报错了,但是如果我传的是引用却不会报错。在文章末尾说

    上代码先:
     

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. int MAX(int a, int b)
    7. {
    8. return a >= b ? a : b;
    9. }
    10. class Data
    11. {
    12. public:
    13. PIMAGE_DOS_HEADER my_dos;//dos头结构
    14. PIMAGE_FILE_HEADER my_file;//file结构
    15. PIMAGE_OPTIONAL_HEADER32 my_optional;//可选PE头结构
    16. PIMAGE_SECTION_HEADER* my_section ;//节表结构
    17. void* Before_Stretch_Data ; //指向拉伸前的内容
    18. void* Stretch_Data ; //指向拉伸后的内容
    19. void* Shrink_Data ; //指向缩小PE结构的内容
    20. Data()
    21. {
    22. my_dos = nullptr;//dos头结构
    23. my_file = nullptr;//file结构
    24. my_optional = nullptr;//可选PE头结构
    25. my_section = nullptr;//节表结构
    26. Before_Stretch_Data = nullptr; //指向拉伸前的内容
    27. Stretch_Data = nullptr; //指向拉伸后的内容
    28. Shrink_Data = nullptr; //指向缩小PE结构的内容
    29. }
    30. ~Data()
    31. {
    32. if (Before_Stretch_Data != nullptr)
    33. {
    34. free(Before_Stretch_Data);
    35. Before_Stretch_Data = nullptr;
    36. }
    37. if (Stretch_Data != nullptr)
    38. {
    39. free(Stretch_Data);
    40. Stretch_Data = nullptr;
    41. }
    42. if (Shrink_Data != nullptr)
    43. {
    44. free(Shrink_Data);
    45. Shrink_Data = nullptr;
    46. }
    47. }
    48. void Copy_Before_Strectch_Data(Data my_data); //只深拷贝Before_Strectch_Data
    49. };
    50. void Data::Copy_Before_Strectch_Data(Data my_data)
    51. {
    52. int size=_msize(my_data.Before_Stretch_Data);
    53. memcpy_s(this->Before_Stretch_Data, size, my_data.Before_Stretch_Data, size);
    54. }
    55. class PE
    56. {
    57. public:
    58. public:
    59. void Readfile(char* filename, Data& my_data); //读取pe文件
    60. void Analyze_PE(Data& my_data); //分析pe结构
    61. void Stretch_PE(Data& my_data); //拉伸pe结构
    62. void Shrink_PE(Data& my_data); //缩小pe结构
    63. void New_Section(char* filename,Data& my_data);//新增节,非扩大节,并写入新的exe文件中
    64. void Expand_Section(Data& my_data, char* filename); //扩大节
    65. int Section_Align(int temp,Data& my_data); //返回内存对齐后的大小
    66. int File_Align(int temp,Data& my_data); //返回文件对齐后的大小
    67. void Copy_Data(Data& my_data);
    68. };
    69. void PE:: Expand_Section(Data& my_data,char* filename)
    70. {
    71. this->Stretch_PE(my_data);
    72. unsigned Size = 0;//扩大节后新的文件大小
    73. Size = my_data.my_optional->ImageBase + Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize),my_data);
    74. Data Expand_Data;
    75. Expand_Data.Stretch_Data= (void*)malloc(Size);
    76. memset(Expand_Data.Stretch_Data, 0, Size);
    77. memcpy_s(Expand_Data.Stretch_Data, _msize(my_data.Stretch_Data), my_data.Stretch_Data, _msize(my_data.Stretch_Data));
    78. Analyze_PE(Expand_Data);
    79. Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData = Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data) + Section_Align(MAX(my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData, my_data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize), my_data);
    80. Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize = Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
    81. Expand_Data.my_optional->SizeOfImage += Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);
    82. void* Temp_Ptr = (char*)Expand_Data.Stretch_Data+ Expand_Data.my_section[Expand_Data.my_file->NumberOfSections - 1]->VirtualAddress+ Section_Align(MAX(my_data.my_section[Expand_Data.my_file->NumberOfSections - 1]->SizeOfRawData, my_data.my_section[Expand_Data.my_file->NumberOfSections - 1]->Misc.VirtualSize),my_data);
    83. int temp_size = Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);
    84. void* Temp_Ptr2 = (char*)my_data.Stretch_Data + my_data.my_section[0]->VirtualAddress;
    85. memcpy_s(Temp_Ptr, temp_size, Temp_Ptr2, temp_size);
    86. Shrink_PE(Expand_Data);
    87. FILE* my_file;
    88. if (fopen_s(&my_file, filename, "wb") != 0)
    89. {
    90. cout << "打开文件失败!" << endl;
    91. }
    92. else
    93. {
    94. Size = _msize(Expand_Data.Shrink_Data);
    95. fwrite(Expand_Data.Shrink_Data, 1, Size, my_file);
    96. cout << "写入成功!" << endl;
    97. }
    98. }
    99. int PE::Section_Align(int temp, Data& my_data)
    100. {
    101. return (temp / my_data.my_optional->SectionAlignment)* my_data.my_optional->SectionAlignment + my_data.my_optional->SectionAlignment;
    102. }
    103. int PE::File_Align(int temp, Data& my_data)
    104. {
    105. return temp / my_data.my_optional->FileAlignment + my_data.my_optional->FileAlignment;
    106. }
    107. void PE::New_Section(char* filename, Data& my_data)
    108. {
    109. unsigned int Size; //Size是新文件的大小,是原来的文件大小加上.VirtualSize和SizeOfRawData较大的那个
    110. Size = my_data.my_optional->SizeOfHeaders;
    111. for (int i = 0;i < my_data.my_file->NumberOfSections; i++)
    112. {
    113. Size += my_data.my_section[i]->SizeOfRawData;
    114. }
    115. Size+= my_data.my_section[0]->SizeOfRawData;//这是最终新的文件的大小
    116. Data New_Data;
    117. New_Data.Before_Stretch_Data = (void*)malloc(Size*1);
    118. memset(New_Data.Before_Stretch_Data, 0, Size);
    119. memcpy_s(New_Data.Before_Stretch_Data, Size, my_data.Before_Stretch_Data, Size - my_data.my_section[0]->SizeOfRawData);//将原来的文件复制过来
    120. Analyze_PE(New_Data);//让New_Data的dos,file,optional,section有数据
    121. //复制新的节表
    122. void* Temp_ptr1 = (char*)my_data.Before_Stretch_Data + 0x98 + my_data.my_file->SizeOfOptionalHeader;
    123. void* Temp_ptr2 = (char*)New_Data.Before_Stretch_Data + 0x98 + my_data.my_file->SizeOfOptionalHeader + my_data.my_file->NumberOfSections * 0x28;
    124. memcpy_s(Temp_ptr2, 0x28, Temp_ptr1, 0x28);
    125. //复制新的节
    126. Temp_ptr1 = (char*)my_data.Before_Stretch_Data + my_data.my_optional->SizeOfHeaders;//指向.text段
    127. Temp_ptr2 = (char*)New_Data.Before_Stretch_Data + Size - my_data.my_section[0]->SizeOfRawData;
    128. memcpy_s(Temp_ptr2, my_data.my_section[0]->SizeOfRawData, Temp_ptr1, my_data.my_section[0]->SizeOfRawData);//复制完.text段作为新增节
    129. //接下来要改Header的各项数据
    130. New_Data.my_file->NumberOfSections++;
    131. New_Data.my_optional->SizeOfImage += my_data.my_section[0]->SizeOfRawData;
    132. Analyze_PE(New_Data);
    133. New_Data.my_section[New_Data.my_file->NumberOfSections - 1]->PointerToRawData = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->PointerToRawData + New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData;
    134. int size;
    135. if (New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->Misc.VirtualSize >= New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData)
    136. {
    137. size = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->Misc.VirtualSize;
    138. }
    139. else
    140. {
    141. size = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData;
    142. }
    143. size = size / my_data.my_optional->SectionAlignment + my_data.my_optional->SectionAlignment;
    144. New_Data.my_section[New_Data.my_file->NumberOfSections - 1]->VirtualAddress = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->VirtualAddress+size;
    145. FILE* my_file;
    146. if (fopen_s(&my_file, filename, "wb") == 0)
    147. {
    148. fwrite(New_Data.Before_Stretch_Data, 1, Size, my_file);
    149. cout << "写入成功!" << endl;
    150. return;
    151. }
    152. else
    153. {
    154. cout << "打开文件失败" << endl;
    155. return;
    156. }
    157. }
    158. void PE::Readfile(char* filename,Data& my_data)
    159. {
    160. unsigned int size;
    161. FILE* datafile;
    162. void* data;
    163. //打开文件
    164. if (fopen_s(&datafile, filename, "rb") != 0)
    165. {
    166. cout << "打开文件失败" << endl;
    167. return;
    168. }
    169. else
    170. {
    171. //获取文件的大小
    172. cout << "打开文件成功!" << endl;
    173. fseek(datafile, 0, SEEK_END);
    174. size = ftell(datafile);
    175. fseek(datafile, 0, SEEK_SET);
    176. if (size == -1L)
    177. {
    178. cout << "文件大小判断失败!" << endl;
    179. return;
    180. }
    181. //申请内存空间把文件内容保存下来
    182. my_data.Before_Stretch_Data = (void*)malloc(size * sizeof(char));
    183. if (fread_s(my_data.Before_Stretch_Data, size, sizeof(char), size, datafile) == 0)
    184. {
    185. cout << "写入数据失败!" << endl;
    186. return;
    187. }
    188. cout << "写入数据成功,成功获取Data!" << endl;
    189. return ;
    190. }
    191. }
    192. //分析PE结构
    193. void PE::Analyze_PE(Data& my_data)
    194. {
    195. if (my_data.Before_Stretch_Data != nullptr)
    196. {
    197. DWORD* Temp_ptr = (DWORD*)my_data.Before_Stretch_Data;
    198. my_data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;
    199. Temp_ptr = (DWORD*)((char*)my_data.Before_Stretch_Data + my_data.my_dos->e_lfanew);
    200. Temp_ptr++;
    201. my_data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;
    202. Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
    203. my_data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;
    204. Temp_ptr = (DWORD*)((char*)my_data.my_optional + my_data.my_file->SizeOfOptionalHeader);
    205. my_data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER) * my_data.my_file->NumberOfSections);
    206. for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
    207. {
    208. my_data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
    209. Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
    210. }
    211. return;
    212. }
    213. else if(my_data.Stretch_Data!=nullptr)
    214. {
    215. DWORD* Temp_ptr = (DWORD*)my_data.Stretch_Data;
    216. my_data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;
    217. Temp_ptr = (DWORD*)((char*)my_data.Stretch_Data + my_data.my_dos->e_lfanew);
    218. Temp_ptr++;
    219. my_data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;
    220. Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
    221. my_data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;
    222. Temp_ptr = (DWORD*)((char*)my_data.my_optional + my_data.my_file->SizeOfOptionalHeader);
    223. my_data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER) * my_data.my_file->NumberOfSections);
    224. for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
    225. {
    226. my_data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
    227. Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
    228. }
    229. return;
    230. }
    231. else if (my_data.Shrink_Data != nullptr)
    232. {
    233. DWORD* Temp_ptr = (DWORD*)my_data.Shrink_Data;
    234. my_data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;
    235. Temp_ptr = (DWORD*)((char*)my_data.Shrink_Data + my_data.my_dos->e_lfanew);
    236. Temp_ptr++;
    237. my_data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;
    238. Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
    239. my_data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;
    240. Temp_ptr = (DWORD*)((char*)my_data.my_optional + my_data.my_file->SizeOfOptionalHeader);
    241. my_data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER) * my_data.my_file->NumberOfSections);
    242. for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
    243. {
    244. my_data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
    245. Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
    246. }
    247. return;
    248. }
    249. cout << "分析pe结构失败!" << endl;
    250. cout << "失败原因,Data类里三个状态的指针皆为空指针!" << endl;
    251. }
    252. //拉伸PE结构 注意看PIMAGE_XXX_HEADER的定义,它们本就是指向结构体的指针
    253. void PE::Stretch_PE(Data& my_data)
    254. {
    255. unsigned Memory_Size = 0;
    256. Memory_Size = my_data.my_optional->SizeOfImage;
    257. my_data.Stretch_Data = (void*)malloc(sizeof(char) * Memory_Size);
    258. memset(my_data.Stretch_Data, 0, Memory_Size);
    259. void* temp_before_stretch_data_ptr = my_data.Before_Stretch_Data;
    260. int size_of_dos = 0x40;
    261. int size_of_junk = 0x40;
    262. int size_of_file = 0x18;
    263. unsigned Size_Of_Optional = my_data.my_file->SizeOfOptionalHeader;
    264. unsigned Size_Of_Section = 0x28;
    265. unsigned Size_Of_Header = size_of_dos + size_of_file + size_of_junk + Size_Of_Optional + Size_Of_Section * my_data.my_file->NumberOfSections;//还未对齐
    266. memcpy_s(my_data.Stretch_Data, Memory_Size, my_data.Before_Stretch_Data, Size_Of_Header);
    267. void* temp_stretch_data = my_data.Stretch_Data;
    268. //现在计算head头对齐后的大小
    269. int Size = Size_Of_Header % my_data.my_optional->SectionAlignment;
    270. Size_Of_Header = my_data.my_optional->SectionAlignment * Size;
    271. for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
    272. {
    273. temp_stretch_data = (void*)((char*)my_data.Stretch_Data + my_data.my_section[i]->VirtualAddress);
    274. temp_before_stretch_data_ptr = (void*)((char*)my_data.Before_Stretch_Data + my_data.my_section[i]->PointerToRawData);
    275. memcpy_s(temp_stretch_data, my_data.my_section[i]->SizeOfRawData, temp_before_stretch_data_ptr, my_data.my_section[i]->SizeOfRawData);
    276. }
    277. cout << "拉伸成功" << endl;
    278. }
    279. void PE::Shrink_PE(Data& my_data)
    280. {
    281. unsigned int Size = 0;
    282. Size = my_data.my_section[my_data.my_file->NumberOfSections - 1]->PointerToRawData + my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
    283. my_data.Shrink_Data = (void*)malloc(Size);
    284. //从Stretch_Data缩小
    285. //复制Heads
    286. memcpy_s(my_data.Shrink_Data, my_data.my_optional->SizeOfHeaders, my_data.Stretch_Data, my_data.my_optional->SizeOfHeaders);
    287. //复制节
    288. void* temp_shrink_data_ptr = my_data.Shrink_Data;
    289. void* temp_stretch_data_ptr = my_data.Stretch_Data;
    290. for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
    291. {
    292. temp_shrink_data_ptr = (void*)((char*)my_data.Shrink_Data + my_data.my_section[i]->PointerToRawData);
    293. temp_stretch_data_ptr = (void*)((char*)my_data.Stretch_Data + my_data.my_section[i]->VirtualAddress);
    294. memcpy_s(temp_shrink_data_ptr, my_data.my_section[i]->SizeOfRawData, temp_stretch_data_ptr, my_data.my_section[i]->SizeOfRawData);
    295. }
    296. cout << "缩小成功" << endl;
    297. return;
    298. }
    299. int main()
    300. {
    301. char filename[100]= "ceshi.exe";
    302. PE my_pe;
    303. Data my_data;
    304. my_pe.Readfile(filename,my_data);
    305. my_pe.Analyze_PE(my_data); //char*& Data, PIMAGE_DOS_HEADER& dos, PIMAGE_FILE_HEADER& file, PIMAGE_OPTIONAL_HEADER32& optional, PIMAGE_SECTION_HEADER*& section
    306. my_pe.Stretch_PE(my_data);
    307. my_pe.Shrink_PE(my_data);
    308. /*char filename2[100] = "666.exe";
    309. my_pe.New_Section(filename2, my_data);*/
    310. char filename3[100] = "555.exe";
    311. my_pe.Expand_Section(my_data,filename3);
    312. return 0;
    313. }

    至于刚刚提到的问题,我查看汇编代码发现了些许端倪
     

    1. 004C2E4B C7 45 FC FF FF FF FF mov dword ptr [ebp-4],0FFFFFFFFh
    2. 004C2E52 8D 4D B8 lea ecx,[Expand_Data]
    3. 004C2E55 E8 08 E4 FF FF call Data::~Data (04C1262h)
    4. 004C2E5A 52 push edx
    5. 004C2E5B 8B CD mov ecx,ebp
    6. 004C2E5D 50 push eax
    7. 004C2E5E 8D 15 98 2E 4C 00 lea edx,ds:[4C2E98h]
    8. 004C2E64 E8 03 E4 FF FF call @_RTC_CheckStackVars@8 (04C126Ch)
    9. 004C2E69 58 pop eax
    10. 004C2E6A 5A pop edx
    11. 004C2E6B 8B 4D F4 mov ecx,dword ptr [ebp-0Ch]
    12. 004C2E6E 64 89 0D 00 00 00 00 mov dword ptr fs:[0],ecx
    13. 004C2E75 59 pop ecx
    14. 004C2E76 5F pop edi
    15. 004C2E77 5E pop esi
    16. 004C2E78 5B pop ebx
    17. 004C2E79 8B 4D F0 mov ecx,dword ptr [ebp-10h]
    18. 004C2E7C 33 CD xor ecx,ebp
    19. 004C2E7E E8 21 E3 FF FF call @__security_check_cookie@4 (04C11A4h)
    20. 004C2E83 81 C4 3C 01 00 00 add esp,13Ch
    21. 004C2E89 3B EC cmp ebp,esp
    22. 004C2E8B E8 4F E4 FF FF call __RTC_CheckEsp (04C12DFh)
    23. 004C2E90 8B E5 mov esp,ebp
    24. 004C2E92 5D pop ebp
    25. 004C2E93 C2 08 00 ret 8

    这是我传值引用的结果,可以看到只调用了Expand_Data这个类的析构函数,符合常理,但是一旦我将void PE:: Expand_Section(Data& my_data,char* filename)改为void PE:: Expand_Section(Data my_data,char* filename) 我们再反汇编,此时就有问题了!

    1. 00AB2E0A C6 45 FC 00 mov byte ptr [ebp-4],0
    2. 00AB2E0E 8D 4D B8 lea ecx,[Expand_Data]
    3. 00AB2E11 E8 4C E4 FF FF call Data::~Data (0AB1262h)
    4. 00AB2E16 C7 45 FC FF FF FF FF mov dword ptr [ebp-4],0FFFFFFFFh
    5. 00AB2E1D 8D 4D 08 lea ecx,[my_data]
    6. 00AB2E20 E8 3D E4 FF FF call Data::~Data (0AB1262h)
    7. 00AB2E25 52 push edx
    8. 00AB2E26 8B CD mov ecx,ebp
    9. 00AB2E28 50 push eax
    10. 00AB2E29 8D 15 64 2E AB 00 lea edx,ds:[0AB2E64h]
    11. 00AB2E2F E8 38 E4 FF FF call @_RTC_CheckStackVars@8 (0AB126Ch)
    12. 00AB2E34 58 pop eax
    13. 00AB2E35 5A pop edx
    14. 00AB2E36 8B 4D F4 mov ecx,dword ptr [ebp-0Ch]
    15. 00AB2E39 64 89 0D 00 00 00 00 mov dword ptr fs:[0],ecx
    16. 00AB2E40 59 pop ecx
    17. 00AB2E41 5F pop edi
    18. 00AB2E42 5E pop esi
    19. 00AB2E43 5B pop ebx
    20. 00AB2E44 8B 4D F0 mov ecx,dword ptr [ebp-10h]
    21. 00AB2E47 33 CD xor ecx,ebp
    22. 00AB2E49 E8 56 E3 FF FF call @__security_check_cookie@4 (0AB11A4h)
    23. 00AB2E4E 81 C4 3C 01 00 00 add esp,13Ch
    24. 00AB2E54 3B EC cmp ebp,esp
    25. 00AB2E56 E8 84 E4 FF FF call __RTC_CheckEsp (0AB12DFh)
    26. 00AB2E5B 8B E5 mov esp,ebp
    27. 00AB2E5D 5D pop ebp
    28. 00AB2E5E C2 20 00 ret 20h

    可以看到他居然调用了my_data的析构!这也是导致程序崩溃的原因,因为在main函数中,函数结束后,也会调用my_data的析构,等于调用了析构函数两次!

    具体原因查了下资料对象作为参数按值传递为什么会调用析构函数?为什么实参中的内容会被修改?_c++ 类作为参数传递 在函数中被修改-CSDN博客

    引用大佬的文章

    对象作为参数按值传递为什么会调用析构函数?为什么实参中的内容会被修改?

    因为对象按值传递时,编译器自动生成的复制构造函数进行了指针的简单拷贝,像指针直接赋值 str=s 一样,而没有拷贝指针指向的内容,这样当你将对象传递给函数时确实会有一个拷贝,但是这个拷贝会有一个指针的拷贝,所以两个对象中的 str 指向的内存一样,在退出函数时,析构销毁了函数中对象中的指针,但不幸的是这样实参对象 str 指向的内容也被销毁。

    哎,c++没学好是这样的,但也算收获蛮多 

     

  • 相关阅读:
    Java版本+企业电子招投标系统源代码+支持二开+招投标系统+中小型企业采购供应商招投标平台
    智能AI系统源码ChatGPT系统源码+详细搭建部署教程+AI绘画系统+已支持OpenAI GPT全模型+国内AI全模型
    PostgreSQL数据库体系结构
    阿里巴巴中国站按关键字搜索工厂数据 API 返回值说明
    Android开发-Mac Android开发环境搭建(Android Studio Mac环境详细安装教程,适合新手)...
    行政人事的日常丨每个人心里都有一团火
    【初阶与进阶C++详解】第十一篇:stack和queue
    【宝塔安装教程】2分钟装好面板,一键管理服务器
    使用CSS变量实现主题定制真的很简单
    LabView中顺序结构的使用
  • 原文地址:https://blog.csdn.net/fzucaicai/article/details/133499655