Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
IvanPryamoy
247 / 1 / 1
Регистрация: 02.01.2013
Сообщений: 31
#1

Как создать объект в новой куче? - C++

19.01.2013, 13:13. Просмотров 1191. Ответов 29
Метки нет (Все метки)

VisualStudio 2012, Win7x64Prof.

Пробую выделить память в куче, а потом с помощью формы "Placement new" разместить в ней объект.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class MyClass
{
public:
    int x;
 
    MyClass()
    {
        x=0;
    }
 
    ~MyClass()
    {
        x=1;
    }
};
 
void MyFunc(const HANDLE hHeap)
{
//выделяем память, все ок
MyClass* placementMemory = (MyClass*) HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, sizeof(MyClass));
 
//пробуем разместить в этой памяти новый объект, ошибка!
MyClass* cl = new (placementMemory) MyClass();
}
Последняя строчка содержит две ошибки (подчеркивания красной линией): при наведении мышью на "placementMemory" всплывает подсказка: "Error: требуется спецификатор типа", а при наведении на "MyClass"- "Error: требуется точка с запятой ";"";

Как осилить гидру?
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.01.2013, 13:13
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Как создать объект в новой куче? (C++):

Не могу понять где объект в куче или в стеке ! - C++
Сразу к примеру: class Zombie; { Soldat soldat; // что солдат внутри зомби делает не спрашивайте String name; int ...

Создать объект стек и создать объект очередь с перегруженными операциями - C++
Помогите, пожалуйста с заданиями. 1. Унарная операция Создать объект стек, перегрузив ++ и -- (как постфиксными, так и префиксными)....

Как создать объект класса в потоке? - C++
Как создать объект класса в потоке? Это вообще возможно?

Как создать объект класса в динамической памяти? - C++
привет. я так понял, можно создать объект в динамической области памяти. либо просто создать объект обычным способом, но чтобы его...

Как создать объект класса с двумя параметрами? - C++
#include <iostream> using namespace std; class rational{ public: rational(int numerator = 0, int denominator =...

Как создать объект с конструктором в интерфейсе другого класса? - C++
struct WorkerInfo { WorkerInfo(int iPay, int iDebt) : pay (iPay), iDebt(debt) {} ~WorkerInfo() {} int pay; // зарплата ...

29
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
19.01.2013, 16:25 #16
Цитата Сообщение от IvanPryamoy Посмотреть сообщение
Такое бывает?
Бывает. Во всяких языках более высокого уровня, где за вас создана куча, а её хендл засунут в thread-local storage, а new растолковано, что нужную кучу надо брать из TLS. А так ручками это сделать надо.
1
DU
1484 / 1130 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2013, 16:30 #17
я бы не сказал что все так просто. указал и забыл. пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Foo
{
   std::string str;
};
 
// Thread1
//создание к контексте потока 1
Foo* foo = new Foo(); // допустим это сработало так, что разместилось в специальном буфере.
 
// Thread2
// работаем в контексте второго потока, у него есть ссылка на объект, который создался в контексте первого
foo->str.resize(100);
// вот тут пересоздается буфер внутри строки, пересоздается в контексте второго потока,
// который размещает динамические объекты как-то по другому. Но перед этим ему нужно
// удалить предыдущий буфер, который был создан в контексте первого. И сделать это нужно корректно.
// Как тут быть? Следить за всем и корректно выделять\освобождать? Как-то все достаточно сложно получается.
0
Igor3D
938 / 536 / 61
Регистрация: 01.10.2012
Сообщений: 2,629
19.01.2013, 16:33 #18
Цитата Сообщение от IvanPryamoy Посмотреть сообщение
А можно как-то потоку указать его кучу, чтобы он все объекты создавал только в ней? Тогда все дополнительные телодвижения (выделение памяти в куче, размещение там каждого объекта) сразу будут не нужны.
Такое бывает?
Ну "подобное" нередко приходится делать. Но телодвижений там раз в 10 больше. Код не знает в какой нитке исполняется, может в неск одновременно
0
IvanPryamoy
247 / 1 / 1
Регистрация: 02.01.2013
Сообщений: 31
19.01.2013, 16:36  [ТС] #19
Цитата Сообщение от DU Посмотреть сообщение
я бы не сказал что все так просто. указал и забыл. пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Foo
{
   std::string str;
};
 
// Thread1
//создание к контексте потока 1
Foo* foo = new Foo(); // допустим это сработало так, что разместилось в специальном буфере.
 
// Thread2
// работаем в контексте второго потока, у него есть ссылка на объект, который создался в контексте первого
foo->str.resize(100);
// вот тут пересоздается буфер внутри строки, пересоздается в контексте второго потока,
// который размещает динамические объекты как-то по другому. Но перед этим ему нужно
// удалить предыдущий буфер, который был создан в контексте первого. И сделать это нужно корректно.
// Как тут быть? Следить за всем и корректно выделять\освобождать? Как-то все достаточно сложно получается.
Ну а если потоки совсем независимы (нет у них никакого взаимодействия: каждый обсчитывает свой файл независимых данных)? Ведь лучше сделать так, чтобы потом не мучиться с отладкой, раздумывая "где тут ошибка?"

Как создать "обертки памяти" в виде отдельных куч для потоков?
0
Igor3D
938 / 536 / 61
Регистрация: 01.10.2012
Сообщений: 2,629
19.01.2013, 16:41 #20
Цитата Сообщение от DU Посмотреть сообщение
// вот тут пересоздается буфер внутри строки, пересоздается в контексте второго потока,
// который размещает динамические объекты как-то по другому. Но перед этим ему нужно
// удалить предыдущий буфер, который был создан в контексте первого. И сделать это нужно корректно.
// Как тут быть? Следить за всем и корректно выделять\освобождать? Как-то все достаточно сложно получается.
Все гораздо хуже. std::string - это "корова", причем без требований атомарности
C++
1
2
3
4
string s1("abc");
string s2 = s1;
((char *) s2.c_str())[0] = 'x';
count << s1 << std::endl << s2;
Увидите неожиданный s1
1
IvanPryamoy
247 / 1 / 1
Регистрация: 02.01.2013
Сообщений: 31
19.01.2013, 16:45  [ТС] #21
Похоже мне придется для своих объектов переопределять опреатор new, а объектами C++ не пользоваться (я кстати, их и не использую. Тот же string заменяю на простые массивы wchar_t).

Последнее можно гарантировать невключением C++ заголовков в файлы.
0
Igor3D
938 / 536 / 61
Регистрация: 01.10.2012
Сообщений: 2,629
19.01.2013, 16:49 #22
Цитата Сообщение от IvanPryamoy Посмотреть сообщение
Ну а если потоки совсем независимы (нет у них никакого взаимодействия: каждый обсчитывает свой файл независимых данных)? Ведь лучше сделать так, чтобы потом не мучиться с отладкой, раздумывая "где тут ошибка?"

Как создать "обертки памяти" в виде отдельных куч для потоков?
Ну раздумывать все равно придется А нужна ли Вам "куча" для каждой нитки? Часто бывает что нет, достаточно неск контейнеров. Выглядит напр так
C++
1
2
3
4
5
6
7
8
void MyCalc( int threadIndex )
{
 vector <int> & data = theData[threadIndex];
 ...
// или так (с указателем)
 if (!theData[threadIndex]) 
  theData[threadIndex] = new vector <int> (100);
}
1
OhMyGodSoLong
~ Эврика! ~
1244 / 993 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
19.01.2013, 16:52 #23
Цитата Сообщение от IvanPryamoy Посмотреть сообщение
Как создать "обертки памяти" в виде отдельных куч для потоков?
Банальный пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>
#include <windows.h>
 
#define USE_TLS
 
#ifdef USE_TLS
DWORD g_heap_TLS_idx;
 
void InitTLS(void)
{
    g_heap_TLS_idx = TlsAlloc();
}
 
void FreeTLS(void)
{
    TlsFree(g_heap_TLS_idx);
}
 
void InitThreadHeap(void)
{
    HANDLE heap = HeapCreate(0, 0, 10 * 1024 * 1024);
    TlsSetValue(g_heap_TLS_idx, heap);
}
 
HANDLE GetThreadHeap(void)
{
    return TlsGetValue(g_heap_TLS_idx);
}
 
void FreeThreadHeap(void)
{
    HeapDestroy(GetThreadHeap());
}
 
void* operator new(size_t size)
{
    return HeapAlloc(GetThreadHeap(), 0, size);
}
 
void operator delete(void* ptr)
{
    HeapFree(GetThreadHeap(), 0, ptr);
}
#endif
 
DWORD WINAPI entry(LPVOID)
{
#ifdef USE_TLS
    InitThreadHeap();
#endif
 
    int *x = new int;
    std::cout << x << "\n";
    delete x;
 
#ifdef USE_TLS
    FreeThreadHeap();
#endif
}
 
int main(int argc, char *argv[])
{
#ifdef USE_TLS
    InitTLS();
#endif
 
    HANDLE thread[2];
    thread[0] = CreateThread(NULL, 0, entry, NULL, 0, NULL);
    thread[1] = CreateThread(NULL, 0, entry, NULL, 0, NULL);
    WaitForMultipleObjects(2, thread, TRUE, 60 * 1000);
 
#ifdef USE_TLS
    FreeTLS();
#endif
    return 0;
}
Если дефайн есть, то те инты в разных потоках создаются в разных кучах (адреса чёрти где разбросаны). Если нет, то в одной и той же (адреса рядом). Никакой синхронизации и т. п., так что выводит иногда криво.

Вот эти куски, что в ифдефах в main() и entry(), вообще должны автомагически вставляться кем-то, чтобы 100% не забыли всё создать и удалить. И чтоб не вызвали по два раза, и т. п.

(Естессно, кроме этого ещё масса приключений впереди: массивы, обработка ошибок, "какая-то падла переопределила вместо меня глобальный new и всё сломалось"...)
1
IvanPryamoy
247 / 1 / 1
Регистрация: 02.01.2013
Сообщений: 31
19.01.2013, 17:03  [ТС] #24
Цитата Сообщение от Igor3D Посмотреть сообщение
Ну раздумывать все равно придется А нужна ли Вам "куча" для каждой нитки? Часто бывает что нет, достаточно неск контейнеров. Выглядит напр так
C++
1
2
3
4
5
6
7
8
void MyCalc( int threadIndex )
{
 vector <int> & data = theData[threadIndex];
 ...
// или так (с указателем)
 if (!theData[threadIndex]) 
  theData[threadIndex] = new vector <int> (100);
}
Спасибо, за пример, но данные очень большие (массивы по 100 млн. чисел, причем массивов несколько). Так что надо все-таки культурненько их разделить (почему я и задался этим вопросом. Ведь если было бы все так просто, как в вашем примере, то для меня надо было бы дурку вызывать )
0
Igor3D
938 / 536 / 61
Регистрация: 01.10.2012
Сообщений: 2,629
19.01.2013, 17:10 #25
Цитата Сообщение от IvanPryamoy Посмотреть сообщение
Спасибо, за пример, но данные очень большие (массивы по 100 млн. чисел, причем массивов несколько). Так что надо все-таки культурненько их разделить (почему я и задался этим вопросом. Ведь если было бы все так просто, как в вашем примере, то для меня надо было бы дурку вызывать )
У меня тоже гигабайтные данные, но никакого "разделения" я не делаю, т.к. не вижу что оно даст. Другое дело что vector (да и др контейнеры std) не годятся для таких данных. Но то уже др вопрос
0
go
Эксперт С++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
19.01.2013, 17:15 #26
DU, что опасного в вашем примере так и не понял. Когда стэк будет чиститься деструктор для строки таки будет вызван.
0
DU
1484 / 1130 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2013, 17:42 #27
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class SimpleClass
{
   int x;
   int y;
};
 
 
{
   char buffer[sizeof(SimpleClass)];
   SimpleClass* ptr = new (buffer) SimpleClass();
   // тут что-то делаем.
   // тут не позвали деструктор. но память не утекла. дектруктор SimpleClass ничего интересного
   // не делает, а сам он размещен в буффере, который на стеке, который корректно уничножится.
   // вроде ничего не утекло.
}
 
{
   char buffer[sizeof(std::string)];
   std::string* ptr = new (buffer) std::string();
   ptr->resise(1000); // вот тут внутри строки выделяется буфер для хранения 1000 символов. и выделяется
                            // он не в буфере на стеке. его надо будет удалить. а делается это в деструкторе строки.
   // тут не позвали деструктор. и вот тут утекла та память, которую строка выделела для хранения 1000 символов
}
это я к тому, что выделять заранее кучу памяти и создавать там объекты и не звать для них деструкторы,
- это может быть чревато. если это делать осознанно - то ок.
0
go
Эксперт С++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
19.01.2013, 22:32 #28
Цитата Сообщение от DU Посмотреть сообщение
// тут не позвали деструктор. и вот тут утекла та память, которую строка выделела для хранения 1000 символов
Я вас не понимаю. Вы говорите очевидные вещи. Естественно надо сделать
C++
1
ptr->~string();
Я думал, что мы обсуждаем вот этот пост Как создать объект в новой куче?
0
DU
1484 / 1130 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
19.01.2013, 22:42 #29
да нет. я рассуждал относительно этого сообщения:
Как создать объект в новой куче?
а конкретно:
и жить счастливо (поскольку утечек у меня нет- на то они и кучи, чтобы разом всю память освобождать).
т.е. жить счастливо просто вернув системе память не получится
0
Igor3D
938 / 536 / 61
Регистрация: 01.10.2012
Сообщений: 2,629
20.01.2013, 11:19 #30
Цитата Сообщение от go Посмотреть сообщение
Я вас не понимаю. Вы говорите очевидные вещи. Естественно надо сделать
C++
1
ptr->~string();
Да как-то это "не выглядит хорошо" Вместо того чтобы "освободить все" мы начинаем "ловить блох" с каждым распределенным.

Др словами эта радость (освободить все) хороша только для POD структур, а что-то "выще травы" попрется делать внутренний new, в итоге себе дороже
0
20.01.2013, 11:19
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.01.2013, 11:19
Привет! Вот еще темы с ответами:

Как создать объект класса? ПРоблемма из-за раздельной компиляции - C++
Есть 4 файла engine.h - базовый класс engine.cpp - реализация методов базового класса car.h - класс поизводный от engine car.cpp -...

Как происходит процесс выделения памяти в стеке и куче - C++
#include &lt;stdio.h&gt; #include &lt;conio.h&gt; #include &lt;windows.h&gt; #include &quot;disc.h&quot; void main() { SetConsoleCP(1251); ...

Создать класс. Символьное поле должно быть задано как объект класса string - C++
решите задачку!) 6. Создать класс. Символьное поле должно быть задано как объект класса string. Написать конструктор по умолчанию,...

Как выделить память для двумерного массива указателей в куче? - C++
Есть массив вида: unsigned char *ddtКак выделить память для такого массива в куче? Должен получиться двумерный массив указателей. Сами...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.