Malloc vs new-Inna wyściółka

Przeglądam cudzy kod C++ dla naszego projektu, który używa MPI do wysokowydajnych obliczeń (10^5 - 10^6 rdzeni). Kod ma umożliwić komunikację między (potencjalnie) różnymi maszynami na różnych architekturach. Napisał komentarz, który mówi coś w stylu:

Zwykle używamy new i delete, ale tutaj używam malloc i free. Jest to konieczne, ponieważ niektóre Kompilatory będą blokować dane w inny sposób, gdy new jest używany, prowadzi do błędów w przesyłaniu danych między różnymi platformami. Tak się nie dzieje z malloc.

To nie pasuje do niczego, co wiem ze standardowych pytań new vs malloc.

Jaka jest różnica między new/delete a malloc / free? wskazuje na pomysł, że kompilator może obliczyć rozmiar obiektu inaczej (ale dlaczego różni się to od użycia sizeof?).

Malloc & placement new vs. new jest dość popularnym pytanie, ale mówi tylko o new używaniu konstruktorów, gdzie malloc nie ma, co nie jest do tego istotne.

Jak malloc rozumie wyrównanie? mówi, że pamięć jest gwarantowana, aby być odpowiednio dopasowane do new lub malloc co jest tym, co wcześniej myślałem.

Zgaduję, że w przeszłości błędnie zdiagnozował swój błąd i wywnioskował, że new i malloc dają różne ilości padding, co chyba nie jest prawdą. Ale nie mogę znaleźć odpowiedz z Google lub w jakimkolwiek poprzednim pytaniu.

Pomóż mi, StackOverflow, jesteś moją jedyną nadzieją!
Author: Community, 2012-11-08

8 answers

IIRC jest jeden wybredny punkt. malloc gwarantuje zwrócenie adresu wyrównanego dla dowolnego typu standardowego. ::operator new(n) jest gwarantowane tylko zwrócenie adresu wyrównanego dla dowolnego standardowego typu nie większego niż n, a jeśli T nie jest typem znakowym, to new T[n] jest wymagane tylko zwrócenie adresu wyrównanego dla T.

Ale ma to znaczenie tylko wtedy, gdy grasz w specyficzne dla implementacji sztuczki, takie jak używanie kilku dolnych bitów wskaźnika do przechowywania FLAG lub w inny sposób poleganie na adres, aby mieć więcej wyrównania niż jest to ściśle potrzebne.

Nie wpływa to na padding wewnątrz obiektu, który musi mieć dokładnie taki sam układ niezależnie od tego, w jaki sposób przydzielono pamięć, którą zajmuje. Trudno więc zrozumieć, w jaki sposób różnica może skutkować błędami w przesyłaniu danych.

Czy jest jakiś znak, co autor tego komentarza myśli o obiektach na stosie lub w globalach, czy jego zdaniem są "wyściełane jak malloc" czy "wyściełane jak nowe"? To może dać wskazówki, skąd wziął się pomysł.

Może jest zdezorientowany, ale może Kod, o którym mówi, jest czymś więcej niż prostą różnicą między malloc(sizeof(Foo) * n) a new Foo[n]. Może bardziej:

malloc((sizeof(int) + sizeof(char)) * n);

Vs.

struct Foo { int a; char b; }
new Foo[n];

To znaczy, że może on mówi "używam malloc", ale oznacza "ręcznie pakuję dane do niezmienionych lokalizacji zamiast używać struktury". W rzeczywistości malloc nie jest potrzebna do ręcznego spakowania struktury, ale nie zdając sobie sprawy, że jest to mniej stopień zamieszania. Konieczne jest zdefiniowanie układu danych przesyłanych przez przewód. Różne implementacje będą umieszczać dane w różny sposób, gdy używana jest struktura .

 25
Author: Steve Jessop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-08 11:49:58

Twój kolega mógł mieć na uwadze magiczne ciasteczko new[]/delete[] (takie informacje implementacja używa podczas usuwania tablicy). Nie byłoby to jednak problemem, gdyby użyto alokacji rozpoczynającej się od adresu zwracanego przez new[] (w przeciwieństwie do alokatorów).

Pakowanie wydaje się bardziej prawdopodobne. Zmiany w ABIs mogą (na przykład) skutkować różną liczbą bajtów końcowych dodanych na końcu struktury (na to ma wpływ wyrównanie, rozważ również tablice). Dzięki malloc można było określić położenie struktury, a tym samym łatwiej przenosić ją do obcego ABI. Zmiany te są zwykle zapobiegane przez określenie wyrównania i pakowania struktur transferowych.

 5
Author: justin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-08 11:58:36

Układ obiektu nie może zależeć od tego, czy został przydzielony za pomocą malloc Czy new. Oba zwracają ten sam rodzaj wskaźnika, a kiedy przekażesz ten wskaźnik do innych funkcji, nie będą wiedzieć, w jaki sposób obiekt został przydzielony. sizeof *ptr zależy tylko od deklaracji ptr, a nie od tego, jak została przypisana.

 3
Author: Barmar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-08 10:44:08

Myślę, że masz rację. Wypełnienie jest wykonywane przez kompilator nie new LUB malloc. Rozważania dotyczące wypełnienia będą miały zastosowanie nawet w przypadku zadeklarowania tablicy lub struktury bez użycia new lub malloc w ogóle. W każdym razie, chociaż widzę, jak różne implementacje new i malloc mogą powodować problemy podczas przenoszenia kodu między platformami, zupełnie nie widzę, jak mogą powodować problemy z transferem danych między platformami.

 3
Author: john,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-30 07:41:51

Kiedy chcę kontrolować układ mojej zwykłej starej struktury danych, z kompilatorami MS Visual używam #pragma pack(1). Domyślam się, że taka dyrektywa prekompilera jest obsługiwana przez większość kompilatorów, jak na przykład gcc.

Konsekwencją tego jest wyrównanie wszystkich pól struktur jeden za drugim, bez pustych przestrzeni.

Jeśli platforma po drugiej stronie zrobi to samo ( tzn. skompiluje swoją strukturę wymiany danych z wypełnieniem 1), to dane pobrane z obu stron justs dobrze pasuje. Tak więc nigdy nie musiałem grać z malloc w C++.

W najgorszym wypadku rozważyłbym przeciążenie nowego operatora, ponieważ wykonuje on pewne trudne rzeczy, zamiast używać malloc bezpośrednio w C++.

 0
Author: Stephane Rolland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-30 09:02:36

To jest moje Dzikie przypuszczenie, skąd to coś pochodzi. Jak wspomniałeś, problem polega na transmisji danych przez MPI.

Osobiście, dla moich skomplikowanych struktur danych, które chcę wysyłać/odbierać przez MPI, zawsze implementuję metody serializacji/deserializacji, które pakują/rozpakowują całość do/z tablicy znaków. Teraz, ze względu na wyściółkę wiemy, że ta wielkość struktury może być większa niż rozmiar jej członków i dlatego trzeba również obliczyć nieprzepuszczone wielkość struktury danych tak, że wiemy, ile bajtów jest wysyłanych/odbieranych.

Na przykład, jeśli chcesz wysyłać / odbierać std::vector<Foo> A przez MPI za pomocą wspomnianej techniki, błędem jest zakładanie, że rozmiar wynikowej tablicy znaków wynosi A.size()*sizeof(Foo) w ogóle. Innymi słowy, każda klasa implementująca metody serialize/deserialize powinna również zaimplementować metodę, która raportuje rozmiar tablicy (lub jeszcze lepiej przechowuje tablicę w kontenerze). To może stać się przyczyną błędu. W ten czy inny sposób nie ma to jednak nic wspólnego z new vs malloc, Jak wskazano w tym wątku.

 0
Author: GradGuy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-30 09:02:46

W c++: newsłowo kluczowe jest używane do przydzielania określonych bajtów pamięci w odniesieniu do pewnej struktury danych. Na przykład, zdefiniowałeś jakąś klasę lub strukturę i chcesz przydzielić pamięć dla jej obiektu.

myclass *my = new myclass();

Lub

int *i = new int(2);

Ale we wszystkich przypadkach potrzebny jest zdefiniowany typ danych (class, struct,union, int, char itd...) i tylko te bajty pamięci zostaną przydzielone, które są wymagane dla jej obiektu/zmiennej. (czyli wielokrotności tego typu danych).

Ale w przypadek metody malloc (), można przydzielić dowolne bajty pamięci i nie trzeba przez cały czas określać typu danych. Tutaj można go zaobserwować w kilku możliwościach malloc ():

void *v = malloc(23);

Lub

void *x = malloc(sizeof(int) * 23);

Lub

char *c = (char*)malloc(sizeof(char)*35);
 0
Author: Rahul Raina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-14 08:11:08

Malloc jest rodzajem funkcji a new to typ danych w c++ w c++, jeśli używamy malloc niż musimy i powinniśmy używać typecast inaczej kompilator daje błąd a jeśli do alokacji pamięci użyjemy nowego typu danych, to nie musimy typecast

 -1
Author: hk_043,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-23 12:28:20