Saya meninjau kode C ++ orang lain untuk proyek kami yang menggunakan MPI untuk komputasi kinerja tinggi (10 ^ 5 - 10 ^ 6 core). Kode ini dimaksudkan untuk memungkinkan komunikasi antara (berpotensi) mesin yang berbeda pada arsitektur yang berbeda. Dia menulis komentar yang mengatakan sesuatu di sepanjang baris:
Kami biasanya menggunakan
new
dandelete
, tapi di sini saya menggunakanmalloc
danfree
. Hal ini diperlukan karena beberapa kompiler akan memasukkan data secara berbeda saatnew
digunakan, yang menyebabkan kesalahan dalam mentransfer data antara platform yang berbeda. Ini tidak terjadi denganmalloc
.
Ini tidak sesuai dengan apa pun yang saya ketahui dari pertanyaan standar new
vs.malloc
Apa perbedaan antara new / delete dan malloc / free? mengisyaratkan gagasan bahwa kompilator dapat menghitung ukuran suatu objek secara berbeda (tetapi mengapa hal itu berbeda dengan menggunakan sizeof
?).
malloc & penempatan baru vs. baru adalah pertanyaan yang cukup populer tetapi hanya berbicara tentang new
menggunakan konstruktor di mana malloc
tidak, yang tidak relevan dengan ini.
bagaimana malloc memahami keselarasan? mengatakan bahwa memori dijamin selaras dengan baik new
atau malloc
yang saya pikirkan sebelumnya.
Dugaan saya adalah bahwa dia salah mendiagnosis bugnya sendiri di masa lalu dan menyimpulkannya new
dan malloc
memberikan jumlah padding yang berbeda, yang menurut saya mungkin tidak benar. Tetapi saya tidak dapat menemukan jawabannya dengan Google atau dalam pertanyaan sebelumnya.
Bantu saya, StackOverflow, Anda satu-satunya harapan saya!
sumber
malloc
dannew
, karenanew
di beberapa lingkungan mengalokasikan blok, menambahkan beberapa data ke awal dan mengembalikan penunjuk ke lokasi tepat setelah data ini. (Saya setuju dengan yang lain, di dalam blok data,malloc
dannew
harus menggunakan jenis bantalan yang sama.)Jawaban:
IIRC ada satu hal yang pilih-pilih.
malloc
dijamin untuk mengembalikan alamat yang sesuai untuk semua tipe standar.::operator new(n)
hanya dijamin untuk mengembalikan alamat yang diselaraskan untuk semua tipe standar tidak lebih dari n , dan jikaT
bukan tipe karakter makanew T[n]
hanya diperlukan untuk mengembalikan alamat yang diselaraskanT
.Tetapi ini hanya relevan ketika Anda memainkan trik khusus implementasi seperti menggunakan beberapa bit bawah penunjuk untuk menyimpan bendera, atau mengandalkan alamat untuk memiliki lebih banyak penyelarasan daripada yang benar-benar dibutuhkan.
Ini tidak memengaruhi padding dalam objek, yang harus memiliki tata letak yang persis sama terlepas dari cara Anda mengalokasikan memori yang ditempati. Jadi sulit untuk melihat bagaimana perbedaan tersebut dapat mengakibatkan kesalahan dalam mentransfer data.
Apakah ada tanda-tanda pendapat penulis komentar tersebut tentang objek di stack atau di global, apakah menurutnya objek "empuk seperti malloc" atau "empuk seperti baru"? Itu mungkin memberi petunjuk dari mana ide itu berasal.
Mungkin dia bingung, tapi mungkin kode dia bicarakan adalah lebih dari perbedaan lurus antara
malloc(sizeof(Foo) * n)
vsnew Foo[n]
. Mungkin lebih seperti:vs.
Artinya, mungkin dia mengatakan "Saya menggunakan malloc", tetapi berarti "Saya mengemas data secara manual ke lokasi yang tidak selaras daripada menggunakan struct". Sebenarnya
malloc
tidak diperlukan untuk mengemas struct secara manual, tetapi gagal untuk menyadari itu adalah tingkat kebingungan yang lebih rendah. Penting untuk menentukan tata letak data yang dikirim melalui kabel. Implementasi yang berbeda akan memberikan data yang berbeda ketika struct digunakan.sumber
char
array tidak pernah empuk sama sekali, jadi saya akan tetap dengan "bingung" sebagai penjelasannya.Rekan Anda mungkin telah
new[]/delete[]
memikirkan cookie ajaib (ini adalah informasi yang digunakan implementasi saat menghapus larik). Namun, ini tidak akan menjadi masalah jika alokasi yang dimulai pada alamat yang dikembalikannew[]
digunakan (berlawanan dengan pengalokasi).Pengepakan tampaknya lebih mungkin. Variasi dalam ABI dapat (misalnya) menghasilkan jumlah byte tambahan yang berbeda yang ditambahkan di akhir struktur (ini dipengaruhi oleh penyelarasan, pertimbangkan juga array). Dengan malloc, posisi struktur dapat ditentukan dan dengan demikian lebih mudah dibawa ke ABI asing. Variasi ini biasanya dicegah dengan menentukan kesejajaran dan pengemasan struktur transfer.
sumber
Tata letak objek tidak bisa bergantung pada apakah itu dialokasikan menggunakan
malloc
ataunew
. Keduanya mengembalikan jenis penunjuk yang sama, dan saat Anda meneruskan penunjuk ini ke fungsi lain, mereka tidak akan tahu bagaimana objek dialokasikan.sizeof *ptr
hanya tergantung pada deklarasiptr
, bukan bagaimana itu ditetapkan.sumber
Saya pikir Anda benar. Pengisian dilakukan oleh kompiler bukan
new
ataumalloc
. Pertimbangan padding akan berlaku bahkan jika Anda mendeklarasikan array atau struct tanpa menggunakannew
ataumalloc
sama sekali. Bagaimanapun, sementara saya dapat melihat bagaimana implementasi yang berbeda darinew
danmalloc
dapat menyebabkan masalah saat memporting kode antar platform, saya benar-benar gagal untuk melihat bagaimana mereka dapat menyebabkan masalah dalam mentransfer data antar platform.sumber
new
sebagai pembungkus yang bagus untukmalloc
tetapi tampaknya dari jawaban lain itu tidak sepenuhnya benar. Konsensus tampaknya bahwa padding harus sama dengan keduanya; Saya pikir masalah dengan mentransfer data antar platform hanya muncul jika mekanisme transfer Anda cacat :)Ketika saya ingin mengontrol tata letak struktur data lama saya, dengan kompiler MS Visual yang saya gunakan
#pragma pack(1)
. Saya kira arahan precompiler seperti itu didukung untuk sebagian besar kompiler, seperti misalnya gcc .Ini memiliki konsekuensi menyelaraskan semua bidang struktur satu di belakang yang lain, tanpa ruang kosong.
Jika platform di ujung lain melakukan hal yang sama (yaitu menyusun struktur pertukaran datanya dengan bantalan 1), maka data yang diambil di kedua sisi akan sesuai. Jadi saya tidak pernah bermain-main dengan malloc di C ++.
Paling buruk saya akan mempertimbangkan membebani operator baru sehingga melakukan beberapa hal rumit, daripada menggunakan malloc langsung di C ++.
sumber
pragma pack
atau serupa? Saya menyadari itu tidak akan menjadi bagian dari standar.Ini adalah tebakan liar saya tentang dari mana benda ini berasal. Seperti yang Anda sebutkan, masalahnya ada pada transmisi data melalui MPI.
Secara pribadi, untuk struktur data saya yang rumit yang ingin saya kirim / terima melalui MPI, saya selalu menerapkan metode serialisasi / deserialisasi yang mengemas / membongkar semuanya ke dalam / dari array karakter. Sekarang, karena padding kita tahu bahwa ukuran struktur bisa lebih besar dari ukuran membernya dan dengan demikian kita juga perlu menghitung ukuran unpadded dari struktur data sehingga kita tahu berapa byte yang dikirim / diterima.
Misalnya jika Anda ingin mengirim / menerima
std::vector<Foo> A
melalui MPI dengan teknik tersebut, salah jika menganggap ukuran array karakter yang dihasilkanA.size()*sizeof(Foo)
secara umum. Dengan kata lain, setiap kelas yang mengimplementasikan metode serialize / deserialize, juga harus mengimplementasikan metode yang melaporkan ukuran array (atau lebih baik lagi menyimpan array dalam container). Ini mungkin menjadi alasan di balik bug. Namun, dengan satu atau lain cara, itu tidak ada hubungannya dengannew
vsmalloc
seperti yang ditunjukkan di utas ini.sumber
Dalam c ++:
new
kata kunci digunakan untuk mengalokasikan beberapa byte tertentu dari memori sehubungan dengan beberapa struktur data. Misalnya, Anda telah menentukan beberapa kelas atau struktur dan Anda ingin mengalokasikan memori untuk objeknya.atau
Tetapi dalam semua kasus Anda memerlukan tipe data yang ditentukan (class, struct, union, int, char dll ...) dan hanya byte memori yang akan dialokasikan yang diperlukan untuk objek / variabelnya. (yaitu; kelipatan dari tipe data itu).
Tetapi dalam kasus metode malloc (), Anda bisa mengalokasikan byte memori apa pun dan Anda tidak perlu menentukan tipe data setiap saat. Di sini Anda dapat mengamatinya dalam beberapa kemungkinan malloc ():
atau
atau
sumber
malloc adalah jenis fungsi dan baru adalah jenis tipe data di c ++ di c ++, jika kita menggunakan malloc daripada kita harus dan harus menggunakan typecast jika tidak kompiler memberi Anda kesalahan dan jika kita menggunakan tipe data baru untuk alokasi memori daripada kita tidak perlu untuk typecast
sumber